2015-10-03 58 views
11

我有一個具有函數指針的類,它可以從外部改變內核函數。C++ lambda - 捕獲成員變量

class Bar 
{ 
    public: 
    int i; 
} 

class Foo 
{ 
    public: 
    std::function<double()> kernel; 
    Bar bar;   
}; 

int main() 
{ 

    Foo f; 
    f.kernel = []() -> double { return i * i; }; //this is not working obviously 

} 

我該如何實現「呈現」行爲,例如,讀取lambda內的類變量。我可以繞過f裏面寫f.bar.i,但這不是很好的解決方案。

+1

'[&f](){return f.i * f.i; }'? –

+0

@KerrekSB我編輯了問題 –

+0

所以你基本上想調用'f.kernel()'和'kernel'應該自動綁定到'f'就像它是一個成員函數? – dhke

回答

17

在C++中14,你可以把它寫成,

f.kernel = [&i = f.bar.i]() -> double { return i * i; }; 

如果你沒有C++ 14,則可以選擇創建另一個變量,

int &i = f.bar.i; 
f.kernel = [&i]() -> double { return i*i; }; 

雖然沒有什麼通過f並寫入f.bar.i錯誤。

+0

尼斯。但是這將內核lambda綁定到'f'的特定實例,不是嗎?因此,如果我做'f2.kernel = f.kernel'並調用'f2.kernel()'我從'f'獲得'i'?但可能不是問題。 – dhke

+1

只是一個編譯第一個例子,用g ++ -std = C++ 11給出的警告:警告:lambda捕獲初始值設定項僅在-std = C++ 14或-std = gnu ++ 14中可用,因此它是一個C++ 14功能 – NathanOliver

+0

@NathanOliver刪除了「相信」。 @dhke是的,如果你將''''從'f'複製到'f2',那麼如果你從兩個實例中調用它,你會使用相同的函數。 – aslg

7

看來是you cannot do so。 沒有構造來創建成員函數lambda。

但你可能可以關注@ KerrekSB的建議,並在除了調度調用仍然獲得成員函數:

class Foo 
{ 
public: 
    double kernel() 
    { 
     _kernel(*this); 
    } 

    std::function<double(Foo &)> _kernel; 
}; 


Foo f; 
f._kernel = [](Foo &f) -> double { return f.i * f.i; }; 
f.kernel() 

注意,你不能說出這兩個領域kernel

+0

我也喜歡這個解決方案。你也可以使'_kernel'成爲靜態的,以便所有實例共享相同的「成員函數」。 – aslg

0

該lambda函數不知道我或酒吧。它怎麼知道?您需要傳遞參考。如果你以不同的方式定義函數體,所以你可以傳遞i作爲參數,並在類中調用它,你應該得到你想要的。