2012-06-19 2 views
3

Я пытаюсь преобразовать код, который использовал другую систему, чтобы использовать Boost.Signals2. Старый код использовал обычный указатель функции как функтор; соединения выполнялись путем вызова конкретного метода с функтором, а отключения выполнялись путем вызова другого метода с тем же самым функтором. По соображениям совместимости я все же хочу поддержать это, хотя я знаю, что это не самый эффективный метод под Signals2.Отключение соединения boost2 с помощью functor

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 :: с той же сигнатурой; оба из них произвели эту ошибку:

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 as. 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

Смежные вопросы