2017-01-23 57 views
3

我試圖讓一個類作爲參數在構造函數中使用一個lambda函數,並且我希望這個函數能夠成爲該類的朋友。對於類的代碼看起來是這樣的:如何製作一個lambda函數的類的朋友?

using func = std::function<void(void)>;  

class foo 
{ 
public: 
    foo(func f) 
    { 
     this->f = f; 
    } 

    func f; 
private: 
    int value_I_want_to_modify; //an int I want to change from the function I've passed in the constructor 
} 

而在main()我會寫這樣的事:

int main() 
{ 
    //this will give an error because I cannot access private members from outside class 
    foo v 
    { 
     [&v](void) { v.value_I_want_to_modify = 0 }; 
    } 
} 

現在我想的功能,以交朋友的類,但我可以」找到一個方法來做到這一點。

+2

如何通過參考lambda傳遞int來代替? – jaggedSpire

+3

讓任何老的拉姆達成爲你的朋友是讓每一個班級成爲你的朋友的一種奇特的方式,因爲他們都可以創建lambda表達式並修改你的班級的膽量。你也可以讓所有的成員變量公開。 – jaggedSpire

+3

拉姆達應該是一個扔掉的東西。如果你需要它足夠的地方,你需要友誼,恕我直言,你需要一個完整的命名對象,而不是一個lambda。 – NathanOliver

回答

2

如何製作一個lambda函數類的朋友?

你不行。這是一個catch-22問題。


如果在定義類之前定義了lambda函數,則無法訪問類的成員變量。

using func = std::function<void(void)>;  

class foo; 

// Trying to define the lambda function before the class. 
// Can't use f.value_I_want_to_modify since foo is not defined yet. 
auto lambda_function = [](foo& f) { f.value_I_want_to_modify = 0;} 

class foo 
{ 
    public: 
     foo(func f) 
     { 
     this->f = f; 
     } 

     func f; 
    private: 
     int value_I_want_to_modify; 
}; 

int main() 
{ 
    foo v{lambda_function}; 
} 

如果您定義的類定義後的lambda函數,你不能讓lambda函數的類的朋友。

using func = std::function<void(void)>; 

class foo 
{ 
    public: 
     foo(func f) 
     { 
     this->f = f; 
     } 

     func f; 
    private: 
     int value_I_want_to_modify; 
}; 

int main() 
{ 
    foo f 
    { 
     // Can't make the lambda function a friend of foo 
     // since it cannot be declared before the class definition. 
     [&f](void) { f.value_I_want_to_modify = 0;} 
    } 
} 

最簡單的解決辦法是修改lambda函數接受一個int&作爲參數,修改它的值。

#include <functional> 

using func = std::function<void(int&)>; 

class foo 
{ 
    public: 
     foo(func f) 
     { 
     this->f = f; 
     this->f(value_I_want_to_modify); 
     } 

    private: 

     func f; 
     int value_I_want_to_modify; 
}; 

int main() 
{ 
    foo v{ [](int& out) { out = 0;} }; 
} 
2

由於(根據定義),您無法將lambda命名爲您的朋友聲明所需的類型。

+0

沒辦法,我可以通過某種方式使變量成爲朋友嗎? –

+2

@MauroF。一個變量不能成爲朋友。 –

2

你不能讓任意的朋友std::function,因爲你不知道什麼時候你寫的朋友聲明它的價值是什麼。就像Je​​sper說的那樣,你也不能讓lambda成爲朋友。

你可以做的是當你調用它時,通過(通過引用)你的內部狀態傳遞給函數。

如果您想要公開多個內部成員,可以將它們包裝在結構中以保持參數列表可管理。

例如。

class foo 
{ 
public: 
    struct state { 
     int value; 
     // any other internal values here 
    }; 

    foo(std::function<void(state&)> fun) : f(fun) {} 
    void run() { f(s); } 

private: 
    state s; 
    std::function<void(state&)> f; 
}; 

如果你真的想要一個無參(零參數)功能,在您的電話的網站,你可以bind參數第一:

class foo 
{ 
    // ... 
    foo(std::function<void(state*)> fun) : f(std::bind(fun, &s)) {} 
    void run() { f(); } 

private: 
    state s; 
    std::function<void(void)> f; 
}; 

(第二版說明,我只是傳遞一個指針到內部狀態以避免reference_wrapper)。