Jak przechować slot zwracany przez boost:bind

1

OK, tu jest dokładnie to: https://godbolt.org/z/GKMrjdfbe

1

std::function oraz zwrotki z bind nie implementują interfejsu ==. Musisz napisać własny wrapper na std::function oraz zaimplementować ten operator. To tak na szybko. Jak będę mieć chwilę może popróbuję wieczorem coś wymóżdżyć.

1

No to teraz widać konkretnie w czym problem.
W twoim kodzie, kompilator narzeka, że operator porównania nie może być wybrany bo są możliwe dwie implementacje do wybrania.
Dziś nie mam czasu, żeby zrozumieć skąd dokładnie wzięła się ta dwuznaczność, nie jest to oczywiste.

2

Problem rozwiązany tak jak należy (a nie tak jak próbuje OP): https://godbolt.org/z/E68eYWKbq

class Handler
{
public:
    Handler(Source & source)
    {
        m_scoped_connection = source.OnStart.connect(boost::bind(&Handler::OnStart, this, _1));
    }

private:
  boost::signals2::scoped_connection m_scoped_connection;

  void OnStart(MyEventArgs& args)
  {
      std::cout << "Zaczelo sie...";
  }
};

I to kasując sporo kodu :).

Swoją drogą, będę jeszcze rozkminiał, czemu przykład od OP się nie kompiluje.

0

@MarekR22: zgaduję, :51:6: error: ambiguous overload for 'operator==' wskazuje Ci, że palnąłem głupotę odn. tego, że te typy nie są porównywalne. Jednakże spojrzyj do dokumentacji: https://www.boost.org/doc/lib[...]tion/faq.html#id-1.3.17.7.2.1

Comparison between boost::function objects cannot be implemented "well", and therefore will not be implemented.

...i dalej tłumaczą, że na skutek szczegółów implementacyjnych to się wysypie właśnie niejednoznaczności, a nie braku operatora.
Co ciekawe dalej piszą

The Signals library has a way around this.

Ciekawe czy signals2 też...

Przykład coby nie być gołosłownym:
https://godbolt.org/z/n3KvejrqW

0

Sorry za posta pod postem:
poczytałem dokładniej dokumentację boost::function i odn. operatora == (f i g to odp. lewy i prawy jego argument):

True when f stores an object of type Functor and one of the following conditions applies:
g is of type reference_wrapper<functor> and f.target<functor>() == g.get_pointer().
g is not of type reference_wrapper<functor> and function_equals(*(f.target<functor>()), g).

I wychodzi na to, że o ile samych boost::function porównać nie można, tak można porównać adresy ich bebechów, ergo można przekazać do connect/disconnect referencje (czyli tu: reference wrappery) na te funktory:

class Handler
{
public:
    Handler(Source & source)
      :m_source(source)
    {
        m_event = boost::bind(&Handler::OnStart, this, _1);
        m_source.OnStart.connect(boost::ref(m_event));
        assert(!m_source.OnStart.empty());
    }

    ~Handler()
    {
        m_source.OnStart.disconnect(boost::ref(m_event));
        assert(m_source.OnStart.empty());
    }

https://godbolt.org/z/7dsfdq9dT

1

A z wykorzystaniem boost::signals2::connection?
I trochę nazewnictwo poprawiłem ;). Bez przechowywania referencji do obiektu źródłowego, bez boost:ref.
https://godbolt.org/z/Wr73KsG9e

0

Miałem to kiedyś fajnie zrobione na pierwszych signalsach, i z tego co pamiętam signals2 wszystko utrudniały.
A teraz signals 1 już są chyba usunięte z nowych wersji Boosta :(

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0