2014-01-24 50 views
2

想象有下面的類:C++ 11:比較lambda表達式

#include <functional> 
#include <vector> 

template<typename T1> class Signaler 
{ 
public: 
    typedef std::function<void (T1)> Func; 

public: 
    Signaler() 
    { 
    } 

    void Call(T1 arg) 
    { 
    for(Int32 i = (Int32)_handlers.size() - 1; i > -1; i--) 
    { 
     Func handler = _handlers[i]; 
     handler(arg); 
    } 
    } 

    Signaler& operator+=(Func f) 
    { 
    _handlers.push_back(f); 
    return *this; 
    } 

    Signaler& operator-=(Func f) 
    { 
    for(auto i = _handlers.begin(); i != _handlers.end(); i++) 
    { 
     if ((*i).template target<void (T1)>() == f.template target<void (T1)>()) 
     { 
     _handlers.erase(i); 
     break; 
     } 
    } 

    return *this; 
    } 

private: 
    std::vector<Func> _handlers; 
}; 

我用它的方式如下:

信號裝置全球:: Signal_SelectionChanged;

class C1 
{ 
public: 
    void Register() 
    { 
     Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); }; 
    } 

    void Unregister() 
    { 
     Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); }; 
    } 

    void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {} 
}; 

class C2 
{ 
public: 
    void Register() 
    { 
     Global::Signal_SelectionChanged += [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); }; 
    } 

    void Unregister() 
    { 
     Global::Signal_SelectionChanged -= [&](SelectionChangedEventArgs* e) { this->selectionChangedEvent_cb(e); }; 
    } 

    void selectionChangedEvent_cb(SelectionChangedEventArgs* e) {} 
}; 

現在,我已經是我所說的「註銷」從C2類的問題,它消除了錯版「拉姆達」的表達,因爲‘拉姆達’看起來相似。

我該如何解決這個問題呢?

任何想法?

感謝

+0

也許最好用一些id來取消註冊?在我製作的信號管理器中,我將處理程序存儲在列表中。註冊函數返回一個指向新處理程序的列表迭代器。取消註冊將其作爲參數並使用它來刪除處理程序。另一種選擇是在int =>處理程序映射中使用整數id和存儲處理程序。 – user2079303

+0

來自兩個'std :: function '的目標可以用你使用的方式進行有意義的比較,所以除非你發佈了一些相關的代碼來顯示你填充該向量,然後嘗試刪除和結果 - 所以我們希望看到你真正的錯誤 - 這個問題是浪費時間.... –

+0

嗨,填充矢量的代碼就在那裏!調用註冊/取消註冊時,請參閱C1和C2類。 – Spectral

回答

1

的問題是,你正在使用std::function::target用型塔t不是存儲在std::function中的對象的類型,所以它返回一個空指針。也就是說,您需要知道存儲在std::function中的對象的實際類型才能夠調用target

即使你打電話target與用於添加回調的拉姆達閉合類型,這將不是,原因有二:第一,拉姆達封閉類型是唯一的(5.1.2p3),所以+=-=有lambda表達式不同的類型,即使它們在語法上是相同的;其次,lambda表達式的閉包類型沒有定義爲operator==(5.1.2p3-6,19-20),所以你的代碼甚至不會編譯。

從lambda轉換到std::bind沒有幫助,因爲綁定類型也沒有定義爲operator==

相反,可以考慮使用一個id來註冊/取消註冊回調。你也可以使用你自己的函子,它定義了operator==,但這將是很多工作。