Jak przechować slot zwracany przez boost:bind

0

Cześć, sytuacja wygląda tak. Mam jakąś metodę, którą podłączam do sygnału:

auto event = boost::bind(&AppManager::Impl::OnStart, this, _1);
cmdReg.OnStart.connect(event);

I później trzeba to rozłączyć:

auto event = boost::bind(&AppManager::Impl::OnStart, this, _1);
cmdReg.OnStart.disconnect(event);

Aż się prosi, żeby zmienna event była składnikiem klasy. Tylko w żaden sposób nie mogę tego ogarnąć. Próbowałem to deklarować jako:

boost::function<void(MyEventArgs&)> event;

Ale się wykrzacza przy budowaniu (czepia się o operator == gdzieś w boost.) Próbowałem to też deklarować jako slot. Ale wszystko na nic. Jest jakiś sposób na to?

2

Pokaż MRE, bo trywialny przykład jest ok https://godbolt.org/z/7Td3rb6Tz

#include<iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>

struct WithBoundField
{
    WithBoundField()
    : fkn(boost::bind(&WithBoundField::method, this, _1))
    {}

    int method(char a)
    {
        std::cout <<"passed " << a << " to method\n";
        return 0;
    };

    boost::function<int(char)> fkn;

};

int main(int, char*[])
{
    WithBoundField x;
    x.fkn('a');
    return 0;
}

BTW, skoro używasz auto to po co boost, jak masz std::function, std::bind itd. (bo to pewnie C++11)?

1

Bez MCVE ciężko powiedzieć, ale szklana kula każe sprawdzić, czy nie chcesz użyć std::ref albo boost::ref (o ile istnieje), bo bind robi kopię argumentów (w przeciwieństwie do np. lambdy).

0

Tylko dalej coś się nie składa co mówisz, bo connectuje ok:
https://godbolt.org/z/KbP8Pf9Gv

0

Pokazałem cały znaczący kod. Reszta:

struct MyEventArgs
{
    String cmdName; //string z zewnętrznej biblioteki
    bool handled;
};

typedef boost::signals2::signal<void(MyEventArgs&)> OnStartEvent;

class ICommandRegistrator
{
public:
  OnStartEvent OnStart;
}

Później w implementacji:

class CommandRegistrator: public ICommandRegistrator
{
public:
    void Start()
   {
       //Tworzę i wypełniam MyEventArgs, a potem
       OnStart(args);
   }
}

No i z drugiej strony podłączam tak, jak pokazałem wyżej.

0

O coś takiego Ci chodzi?

class CommandRegistrator: public ICommandRegistrator
{
public:
    boost::function<void(MyEventArgs&)> bfkn;

    CommandRegistrator()
    {
        bfkn = boost::bind(boost::ref(OnStart), _1);
    }
    void Start()
   {
       MyEventArgs args{"abcd", false};
    //    OnStart(args);
        bfkn(args);
   }
};
0

Nie, ja się pytam, jak to przechować w innej klasie. Kod z pierwszego postu pochodzi z zupełnie innej klasy, cmdReg jest obiektem CommandRegistrator

0

No tak samo. Funktor (a tym jest OnStart) może być "bound directly"

    CommandRegistrator cmdreg;
    boost::function<void(MyEventArgs&)> boundF;
    boundF = boost::bind(boost::ref(cmdreg.OnStart), _1);
2

@Juhas Ty zakładasz, że siedzimy w twojej głowie lub widzimy twój monitor.
Musisz zdać sobie sprawę, że my nie wiemy co robisz, jaki masz kod i na czym polega twój problem, ergo musisz dostarczyć wszystkie niezbędne informacje.

To zdanie:

Juhas napisał(a):

Aż się prosi, żeby zmienna event była składnikiem klasy. Tylko w żaden sposób nie mogę tego ogarnąć. Próbowałem to deklarować jako:

boost::function<void(MyEventArgs&)> event;

Ale się wykrzacza przy budowaniu (czepia się o operator == gdzieś w boost.) Próbowałem to też deklarować jako slot. Ale wszystko na nic. Jest jakiś sposób na to?

Dostarcz MCVE (minimalny kompletny weryfikowalny przykład) w którym odtwarzasz błąd z brakującym operatorem ==.
Jak nie potrafisz to wklej pełen log kompilatora (od pierwszego błędu do dołu), bo operator == gdzieś w boost to nie jest opis problemu, tylko zgłoszenie dla jasnowidza.

Coś takiego może być dobrym punktem startowym (próbowałem odtworzyć twój problem na podstawie dostarczonych danych, ale wszystko działa).

4

Dobra chyba mam MCVE: https://godbolt.org/z/6oEnqz36a
Po prostu jeden z argumentów, które są potrzebne dla boost::bind są nieporównywalne.
Ergo boost::bind nie jest w stanie wygenerować operatora porównania (równości).
Efekt końcowy jest taki, że próba wykonania disconnect z argumentem jest niemożliwa od wykonania, bo nie ma jak wykonać porównania na tym obiekcie przekazanym do disconnect, więc nie wiadomo, które połączenie należy zerwać.

W danych, które podałeś nie ma żadnego argumentu bind, którego nie da się porównywać. Wygląda na to, że jednak jestem jasnowidzem :).

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