我剛剛做了一些實驗,最近使用了函數式響應式編程,它是什麼,當我試圖在C++中實現類似的東西時,我轉向lambda尋求幫助。我想出了這樣的開始,lambda和他們的捕獲值
template<class T>
class Reactive
{
public:
Reactive(T data)
{
m_Data = data;
}
Reactive(std::function<T()> func, T data)
{
m_Data = data;
m_Affecter = func;
}
template<class H>
Reactive & operator+(const H & rhs)
{
m_Data += rhs;
return *this;
}
template<class H>
Reactive operator+(Reactive<H> & rhs)
{
std::function<decltype(m_Data + rhs.m_Data)()> func;
if (!rhs.m_Affecter)
func = [&](){return m_Data + rhs.m_Data;};
else
func = [&](){return m_Data + rhs.m_Affecter();};
return Reactive<decltype(m_Data + rhs.m_Data)> (func, m_Data + rhs.m_Data);
}
Reactive & operator=(const T & data)
{
m_Data = data;
return *this;
}
Reactive & operator=(const Reactive & rhs)
{
m_Data = rhs.m_Data;
m_Affecter = rhs.m_Affecter;
return *this;
}
T & Get()
{
return m_Data;
}
void Update()
{
m_Data = m_Affecter();
}
private:
std::function<T()> m_Affecter;
T m_Data;
};
它只支持添加到目前爲止。我試圖創建一個名爲被動對象的對象,它可以圍繞任何其他類型進行封裝,除了當對其執行數學運算時,會創建一個lambda,並在那裏進行該操作,以便記住所做的事情並在其中一個影響值發生變化時再次執行(在調用更新函數之後)。例如,如果我要這樣做。
Reactive<int> cheh = 0;
Reactive<int> meh = 3;
Reactive<int> peh = 7;
cheh = meh + peh;
meh = meh + 4;
cheh.Update();
std::cout << cheh.Get();
然後繼承人會發生什麼。總結第五行中的兩個Reactives將使另一個Reactive與它們的兩個值相加爲10,並將它的影響器設置爲做類似這樣的lambda,& {meh.m_Data + peh.m_Data}。那Reactive就會分配給cheh。當m_meh的值增加了4,cheh被更新時,它的影響力被調用,新的值爲14,這就是打印到屏幕上的內容,完全按照我的意圖。
但是後來我開始思考,如果參與cheh的影響者的Reactives中的一個退出範圍會怎樣。如果處理不正確,程序應該會出錯。 所以我這樣做,
Reactive<int> cheh = 0;
Reactive<int> meh = 3;
{
Reactive<int> peh = 7;
cheh = meh + peh;
peh = peh + 4;
}
cheh.Update();
std::cout << cheh.Get();
在更新時調用點,發生在他affecter無功正常皮膚已經超出了範圍,不再存在。然而,這個程序和cheh的影響者成功執行,並且像以前一樣打印出14個。我知道lambda中的值是通過引用捕獲傳入的,那麼,受害者函數如何仍然可以訪問引用peh?通過引用傳遞給lambda表達式的對象或整型類型是否強制它們在lambda存在時一直存在?有東西聞起來很腥......
看起來不像是這樣,但這實際上是個好消息。聽起來好像調試會很糟糕,如果lambda強迫它繼續存在的話。我會建立一個信號插槽系統,通知Reactives當其他反應參與那裏影響者被破壞,這將影響零。 Thankee親切! – FatalCatharsis 2013-04-06 17:13:16
@FatalCatharsis:很高興幫助:) – 2013-04-06 17:16:17