LINUX.ORG.RU

Boost::signals и «внутренние» переменные объекта функции


0

1

Что-то мне совершенно взрывает мозги boost::signals2, и кстати boost::signals ведет себя точно так же.

Допустим, есть такой код:

#include <iostream>
#include <boost/signals2.hpp>

using namespace std;
using namespace boost::signals2;

class test_class {
public:
    int a;
    test_class() : a(0) {};
    int operator()() {
        a++;
        return a;
    }
};

int main(int argc, char *argv[])
{
    signal< int()> sig;
    test_class test;
    sig.connect(test);
    cout << *sig() << endl;
    cout << test.a << endl;
}

Он выводит следующее:

$ ./a.out
1
0

Насколько я понимаю всю парадигму сигнал-слотов, sig() должен вызвать test.operator() и соответственно вернуть его значение. По разумной логике, test.a тогда должен быть 0+1=1 в момент получения его значения. А он почему-то 0!

ЧЯДНТ, или где я не понимаю идею?

Сразу оговорюсь, я нашел воркэраунд, но он НАСТОЛЬКО горбатый, что страшно о нем даже думать...

И да, на всякий случай,

//...snip...
    cout << test() << endl;
    cout << test.a << endl;
//...snip...
выдает положенные ему
$ ./a.out
1
1


Ответ на: комментарий от Begemoth

Ну хорошо, допустим сигнал за каким-то хреном создает локальную копию объекта. Как этого избежать? Не могу я отказаться от переменных в классе.

livid
() автор топика
Ответ на: комментарий от livid

допустим сигнал за каким-то хреном создает локальную копию объекта

Этот какой-то хрен - поддержка использования boost::bind и подобных в качестве слотов.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

поддержка использования boost::bind и подобных в качестве слотов

А как это работает? В данном случае, например:

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

using namespace std;
using namespace boost::bind;
using namespace boost::signals2;

struct test_class
{
   int a;
   test_class() : a(0) { return; };
   int operator () (void)
   {
      return ++a;
   }
};

int main(int argc,char** argv)
{
   typedef signal<int (void)>::slot_type slot_type;
   signal<int (void)> sig;
   test_class test;
   sig.connect(slot_type(boost::bind(&test_class::operator (),&test)));
   cout << *sig() << endl;
   cout << test.a << endl;
}

Здесь всё в порядке, внутреннее состояние объекта изменяется.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

В данном случае у тебя копируется объект, созданный функцией bind, возможно указатель на test, ей переданный, но не сам объект test.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Т.е. bind создаёт что-то типа

struct bound_exp
{
  test_class* p;
  void test_class::*f ();

  void operator() () { p->*f(); }
};

bind копирует те значения, которые ты ему передаешь. Передашь указатель - скопирует указатель, но не объект на который он указывает. Чтобы bind не копировал переданное значение используется boost::ref.

Begemoth ★★★★★
()
Ответ на: комментарий от P1XeL

Ref-то я и не заметил. Спасибо, это сильно лучше, чем оборачивать в bind, что пришло в голову сразу.

livid
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.