2012-06-19 28 views
3

我試圖轉換一些使用不同系統的代碼來使用Boost.Signals2。舊代碼使用常規函數指針作爲函數;連接是通過調用具有函子的特定方法完成的,並且通過使用完全相同的函數調用另一個方法來完成斷開連接。出於兼容性原因,我仍然希望支持這一點,儘管我知道這不是Signals2下最有效的方法。通過函子斷開boost信號連接

namespace bs2 = boost::signals2; 
class Foo 
{ 
    typedef bs2::signal<void (const Foo *foo)> UpdateEvent; 
    UpdateEvent m_UpdateEvent; 

public: 
    typedef UpdateEvent::slot_type UpdateCallback; 

    bs2::connection Register(const UpdateCallback& callback) 
    { 
     return m_UpdateEvent.connect(callback); 
    } 

    void Unregister(const UpdateCallback& callback) 
    { 
     m_UpdateEvent.disconnect(callback); 
    } 
}; 

上述(簡化的)碼能正常工作的連接,但取消註冊方法不會在VS2008編譯:

T:\boost\boost_1_47_0\boost/function_equal.hpp(17) : error C2678: binary '==' : no operator found which takes a left-hand operand of type 'const Foo::UpdateCallback' (or there is no acceptable conversion) 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(808): could be 'bool boost::operator ==<T>(const boost::function_base &,Functor)' 
    with 
    [ 
     T=Foo::UpdateCallback, 
     Functor=Foo::UpdateCallback 
    ] 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(817): or  'bool boost::operator ==<F>(Functor,const boost::function_base &)' 
    with 
    [ 
     F=Foo::UpdateCallback, 
     Functor=Foo::UpdateCallback 
    ] 
    C:\Program Files\Microsoft SDKs\Windows\v6.0A\include\guiddef.h(192): or  'int operator ==(const GUID &,const GUID &)' [found using argument-dependent lookup] 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(746): or  'bool boost::operator ==(const boost::function_base &,boost::detail::function::useless_clear_type *)' 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(758): or  'bool boost::operator ==(boost::detail::function::useless_clear_type *,const boost::function_base &)' 
    T:\boost\boost_1_47_0\boost/blank.hpp(58): or  'bool boost::operator ==(const boost::blank &,const boost::blank &)' 
    while trying to match the argument list '(const Foo::UpdateCallback, const Foo::UpdateCallback)' 
    T:\boost\boost_1_47_0\boost/function_equal.hpp(24) : see reference to function template instantiation 'bool boost::function_equal_impl<F,G>(const F &,const G &,long)' being compiled 
    with 
    [ 
     F=Foo::UpdateCallback, 
     G=Foo::UpdateCallback 
    ] 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(811) : see reference to function template instantiation 'bool boost::function_equal<Functor,Functor>(const F &,const G &)' being compiled 
    with 
    [ 
     Functor=Foo::UpdateCallback, 
     F=Foo::UpdateCallback, 
     G=Foo::UpdateCallback 
    ] 
    T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(527) : see reference to function template instantiation 'bool boost::operator ==<T>(const boost::function_base &,Functor)' being compiled 
    with 
    [ 
     T=Foo::UpdateCallback, 
     Functor=Foo::UpdateCallback 
    ] 
    T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(221) : see reference to function template instantiation 'void boost::signals2::detail::signal1_impl<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::do_disconnect<T>(const T &,boost::mpl::bool_<C_>)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback, 
     C_=false 
    ] 
    T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(691) : see reference to function template instantiation 'void boost::signals2::detail::signal1_impl<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::disconnect<T>(const T &)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback 
    ] 
    .\Foo.cpp(72) : see reference to function template instantiation 'void boost::signals2::signal1<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::disconnect<Foo::UpdateCallback>(const T &)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback 
    ] 

所以,不知何故函數對象不能相比於自身?我也嘗試使用slot_function_type作爲UpdateCallback,並且明確地將它指定爲具有相同簽名的boost :: function;這兩個人產生這個錯誤,而不是:

T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(527) : error C2666: 'boost::signals2::detail::operator ==' : 4 overloads have similar conversions 
    T:\boost\boost_1_47_0\boost/function/function_template.hpp(997): could be 'void boost::operator ==<R,T0>(const boost::function1<R,T0> &,const boost::function1<R,T0> &)' [found using argument-dependent lookup] 
    with 
    [ 
     R=void, 
     T0=const Foo * 
    ] 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(817): or  'bool boost::operator ==<boost::function<Signature>>(Functor,const boost::function_base &)' [found using argument-dependent lookup] 
    with 
    [ 
     Signature=void (const Foo *), 
     Functor=boost::function<void (const Foo *)> 
    ] 
    T:\boost\boost_1_47_0\boost/function/function_base.hpp(808): or  'bool boost::operator ==<T>(const boost::function_base &,Functor)' [found using argument-dependent lookup] 
    with 
    [ 
     T=Foo::UpdateCallback, 
     Functor=Foo::UpdateCallback 
    ] 
    or  'built-in C++ operator==(void (__thiscall boost::function1<R,T0>::dummy::*)(void), void (__thiscall boost::function1<R,T0>::dummy::*)(void))' 
    with 
    [ 
     R=void, 
     T0=const Foo * 
    ] 
    while trying to match the argument list '(boost::function<Signature>, const Foo::UpdateCallback)' 
    with 
    [ 
     Signature=void (const Foo *) 
    ] 
    T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(221) : see reference to function template instantiation 'void boost::signals2::detail::signal1_impl<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::do_disconnect<T>(const T &,boost::mpl::bool_<C_>)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback, 
     C_=false 
    ] 
    T:\boost\boost_1_47_0\boost/signals2/detail/signal_template.hpp(691) : see reference to function template instantiation 'void boost::signals2::detail::signal1_impl<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::disconnect<T>(const T &)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback 
    ] 
    .\Foo.cpp(72) : see reference to function template instantiation 'void boost::signals2::signal1<R,T1,Combiner,Group,GroupCompare,SlotFunction,ExtendedSlotFunction,Mutex>::disconnect<Foo::UpdateCallback>(const T &)' being compiled 
    with 
    [ 
     R=void, 
     T1=const Foo *, 
     Combiner=boost::signals2::optional_last_value<void>, 
     Group=int, 
     GroupCompare=std::less<int>, 
     SlotFunction=boost::function<void (const Foo *)>, 
     ExtendedSlotFunction=boost::function<void (const boost::signals2::connection &,const Foo *)>, 
     Mutex=boost::signals2::mutex, 
     T=Foo::UpdateCallback 
    ] 

所以我想它已經從太少的選擇走了太多。我該如何解決這個問題?

+0

看看以下兩個環節:1)http://www.boost.org/doc/libs/1_49_0/doc/html/function/faq.html#id1549884 2)的http:// www.boost.org/doc/libs/1_49_0/doc/html/function/tutorial.html#id1530326 –

+0

嗯,我想這可能解釋爲什麼它不直接工作,但不是如何使它工作。 – Miral

+1

兩年後,我有同樣的問題。如果我找到答案,我會發布答案。 – sgryzko

回答

0

boost :: function沒有實現operator ==,所以我們不能像f1 == f2那樣進行比較。 當boost :: signal庫需要通過使用boost :: function作爲參數從信號 中斷開一個函數時,會導致這個問題。 boost :: signal通過比較參數和它自己的函數來嘗試查找函數,並且會導致錯誤。我的解決方案如下。還提出了其他可能的解決方案,如存儲連接....如果我的方法適合您,您應該選擇它,因爲它不存儲任何內容,因此您不需要處理手動連接管理。

class Button { 
public: 

    typedef void (*EventHandler)(); 
    typedef boost::signal<void()> Event; 

    Button() { 
    } 

    virtual ~Button() { 
    } 

    void addClickHandler(EventHandler handler) { 
     clickEvent.connect(handler); 
    } 

    void removeClickHandler(EventHandler handler) { 
     clickEvent.disconnect(handler); 
    } 

    void click() { 
     clickEvent(); 
    } 

private: 
    Event clickEvent; 
}; 

void print() { 
    cout << "print" << endl; 
} 

void app1_TestButton() { 
    Button b; 
    b.addClickHandler(print); 
    b.click(); 

    b.removeClickHandler(print); 
    b.click(); 
} 
+0

這不是一個真正的解決方案,因爲它只與裸函數指針一起工作,該指針根據定義不能包含任何上下文,因此在不能依賴全局單例的實際應用程序中基本沒用。 – Miral