Russian Qt Forum
Май 21, 2024, 03:27 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 ... 3 4 [5] 6   Вниз
  Печать  
Автор Тема: Protected вызов сигналов в Boost.Signals2  (Прочитано 33871 раз)
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #60 : Октябрь 18, 2015, 20:15 »

Я, вообще-то, в самом первом ответе предложил Улыбающийся

Сигналы, описанные в секции Q_SIGNALS, не должны являться частью интерфеса.
А ту часть интерфейса, которая должна эмитировать сигналы, делаете защищенной.
После этого только наследники вашего класса смогут эмитировать нужные сигналы.
Все остальное - от лукавого Улыбающийся

Ведь идеологая сигнал-слот в том и состоит, чтобы находиться "сверху" над объектной моделью и обеспечивать коммуникацию между объектами.
Разработчика не должна волновать потенциальная возможность эмитирования сигнала из другого класса.
Есть много способов сделать что-либо "по другому", но тот, кто пытается микроскопом гвозди забивать - сам себе злобная буратинка Улыбающийся

Как уже говорил Old, документируйте интерфейс не в плане "а вот это делать низя!", а в плане "чтобы эмитировать такой-то сигнал, наследуйтесь от класса и вызовите защищенный метод". Это будет лучшим решением проблемы.
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #61 : Октябрь 18, 2015, 20:23 »

Прошу прощения за ошибки) Это всё виноват товарищ Racheengel .. Накаркал тогда про мою хрестоматийную минималистичную клавиатуру, и через пару дней на неё вылили бокал вина(( Вот теперь сижу с мультимедийной, такой непривычной..

Ну вот, пригодился же подарог Улыбающийся
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #62 : Октябрь 18, 2015, 21:02 »

Сигналы, описанные в секции Q_SIGNALS, не должны являться частью интерфеса.
А ту часть интерфейса, которая должна эмитировать сигналы, делаете защищенной.
После этого только наследники вашего класса смогут эмитировать нужные сигналы.
Все остальное - от лукавого Улыбающийся

Спасибо, что объяснили Улыбающийся. Получается всё довольно просто Улыбающийся. И даже идеология появилась. А так же интерфейсы, которые уже упоминались в этой теме, но примера я так и не дождался.

Конкретно с использованием boost::signals2 такое можно реализовать? Если да, то насколько это просто/сложно. Если нет, то почему? Сигналы буста вписываются в идеологию и интерфейсы?
Записан

Пока сам не сделаешь...
Racheengel
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2679


Я работал с дискетам 5.25 :(


Просмотр профиля
« Ответ #63 : Октябрь 18, 2015, 21:50 »

под интерфейсом имеется в виду следующее (вроде, еще Верес про них тоже писал):

Код:
class IDoStuff
{
public:
  virtual void doSometning() = 0;
};


class CDoStuff: public QObject, piblic IDoStuff
{
  Q_OBJECT
public:
  virtual void doSometning()
  {
      // some stuff

      emitSomeSignal();

      // some another stuff
  }

Q_SIGNALS:
  void someSignal();

protected:
  void emitSomeSignal()
  {
    emit someSignal();
  }
};

В этом случае через интерфейс IDoStuff можно будет получить доступ извне только к СDoStuff::doSometning(), который внутри может быть имплементирован как на слотах, так и на шаблонах индусского уровня. Никакой emit СDoStuff::someSignal() не пройдет)

А если вы отнаследуетесь от CDoStuff, не указывая макрос Q_OBJECT, то не сможете вообще ничего эмитить напрямую. Только через вызов emitSomeSignal().
Записан

What is the 11 in the C++11? It’s the number of feet they glued to C++ trying to obtain a better octopus.

COVID не волк, в лес не уйдёт
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #64 : Октябрь 19, 2015, 04:52 »

Конкретно с использованием boost::signals2 такое можно реализовать? Если да, то насколько это просто/сложно. Если нет, то почему? Сигналы буста вписываются в идеологию и интерфейсы?
Я уже "потерял нить", какое "такое"? Улыбающийся Под Вашим (тлетворным) влиянием открыл доку и прочитал. Ну первые 2 примера попытался осознать (вполне успешно), остальное "ознакомился" (пролистал). Ничего страшного, и очень приятно что для использования просто "подкинуть хедер". Что касается "защищенного вызова" (если разговор еще об этом), то там сигнал - конкретная переменная, ну и прячьте ее обычными средствами языка, какие-то спец средства в самой системе слот/сигнал не нужны.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #65 : Октябрь 19, 2015, 17:46 »

Я уже "потерял нить", какое "такое"? Улыбающийся

"Такое" описано в цитате двумя строчками выше того моего предложения со словом "такое". А так же, более подробно, в первом сообщении этой темы Улыбающийся. Я не устану на него ссылаться Улыбающийся.

Под Вашим (тлетворным) влиянием открыл доку и прочитал. Ну первые 2 примера попытался осознать (вполне успешно), остальное "ознакомился" (пролистал). Ничего страшного, и очень приятно что для использования просто "подкинуть хедер".

Влияние хоть и тлетворное, зато вы познакомились с сигналами буста, которые вполне приятны в использовании Улыбающийся.

Что касается "защищенного вызова" (если разговор еще об этом), то там сигнал - конкретная переменная, ну и прячьте ее обычными средствами языка, какие-то спец средства в самой системе слот/сигнал не нужны.

Замечательно Улыбающийся. Теперь спрячьте определение сигнала в разделе protected и обеспечьте возможность подключаться/отключаться к ним любому желающему. Штуки четыре для начала, вида:
Цитировать
    void visibleChanged(bool visible);
    void enabledChanged(bool enable);
    void positionChanged(int x, int y);
    void sizeChanged(int height, int width);

под интерфейсом имеется в виду следующее (вроде, еще Верес про них тоже писал):
Код:
class IDoStuff
{
public:
  virtual void doSometning() = 0;
};
...

В этом случае через интерфейс IDoStuff можно будет получить доступ извне только к СDoStuff::doSometning(), который внутри может быть имплементирован как на слотах, так и на шаблонах индусского уровня. Никакой emit СDoStuff::someSignal() не пройдет)

А если вы отнаследуетесь от CDoStuff, не указывая макрос Q_OBJECT, то не сможете вообще ничего эмитить напрямую. Только через вызов emitSomeSignal().

Это всё тоже замечательно, но где там слова boost::signals2::signal? Где в интерфейсе IDoStuff методы для подключения и отключения сигналов? Конкретный пример с использованием boost::signals2 можете нарисовать? Улыбающийся Подробности в этом же сообщении чуть выше, обращённые к Igors.
Записан

Пока сам не сделаешь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #66 : Октябрь 19, 2015, 20:09 »

Цитировать
Теперь спрячьте определение сигнала в разделе protected и обеспечьте возможность подключаться/отключаться к ним любому желающему. Штуки четыре для начала, вида:
Цитировать
   void visibleChanged(bool visible);
    void enabledChanged(bool enable);
    void positionChanged(int x, int y);
    void sizeChanged(int height, int width);

Вообще и такое, в принципе, возможно реализовать (используя tuple):

Код
C++ (Qt)
class Demo
{
public:
   enum { visibleChanged,
          enabledChanged,
          positionChanged,
          sizeChanged
      };
 
   template <size_t SignalID, class Slot>
   void connect(Slot slot)
   {
       std::get<SignalID>(signal_map).connect(slot);
   }
 
   template <size_t SignalID, class Slot>
   void disconnect(Slot slot)
   {
       std::get<SignalID>(signal_map).disconnect(slot);
   }
 
   template <size_t SignalID, class ...Args>
   void emit(Args ...args)
   {
       std::get<SignalID>(signal_map)(args...);
   }
 
protected:
   typedef std::tuple< signal<void(bool)>,
                       signal<void(bool)>,
                       signal<void(int, int)>,
                       signal<void(int, int)>> signal_map_t;
 
   signal_map_t signal_map;
};
 
void func(bool)
{
   std::cout << "ok" << std::endl;
}
 
int main()
{
   Demo demo;
   demo.connect<Demo::visibleChanged>(&func);
   demo.emit<Demo::visibleChanged>(true);
   retrun 0;
}
 

Ну или то же самое но с X-макросами:
Код
C++ (Qt)
class Demo
{
public:
#define SIGNALS \
   X(signal<void(bool)>,       visibleChanged), \
   X(signal<void(bool)>,       enabledChanged), \
   X(signal<void(int, int)>,    positionChanged), \
   X(signal<void(int, int)>,    sizeChanged)
 
#define X(a,b) b
   enum { SIGNALS };
#undef X
 
   template <size_t SignalID, class Slot>
   void connect(Slot slot)
   {
       std::get<SignalID>(signal_map).connect(slot);
   }
 
   template <size_t SignalID, class Slot>
   void disconnect(Slot slot)
   {
       std::get<SignalID>(signal_map).disconnect(slot);
   }
 
   template <size_t SignalID, class ...Args>
   void emit(Args ...args)
   {
       std::get<SignalID>(signal_map)(args...);
   }
 
protected:
#define X(a,b) a
   typedef std::tuple<SIGNALS> signal_map_t;
#undef X
 
   signal_map_t signal_map;
};
 


Но это так, просто к слову.. Что в принципе возможности это сделать есть..
« Последнее редактирование: Октябрь 19, 2015, 20:12 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #67 : Октябрь 19, 2015, 22:37 »

Вообще и такое, в принципе, возможно реализовать (используя tuple):
...
Вариант с макросами пока пропустим, а вот на шаблонах интересно Улыбающийся.

Нужно продвинуться дальше, с наследованием. Допустим мы смирились с перечислением индексов сигналов в enum и их определением в tuple. Я правильно понимаю, что эти все connect, disconnect, emit придётся копипастить в каждый класс, где объявляются сигналы? Вариант, что это можно записать в макросы, более короткие и безобидные, пока тоже пропустим. Если бы всё было так просто, то эти шаблонные методы можно было бы вынести в базовый класс, и они бы "распространились" на все дочерние. Эти три метода можно ещё как-то "ушаблонить" чтобы не копипастить? Улыбающийся Mixin'ом каким, или ещё чем.

Например, написать внешние функции connect и disconnect, а для классов с сигналами создать потомков конкретно для заданной функции. Как-то так:
Код
C++ (Qt)
class Demo
{
public:
   enum { visibleChanged,
          enabledChanged,
          positionChanged,
          sizeChanged
      };
 
   void test()
   {
       emit<visibleChanged>(true);
   }
 
protected:
   template <size_t SignalID, class ...Args>
   void emit(Args ...args)
   {
       std::get<SignalID>(signal_map)(args...);
   }
 
   typedef std::tuple< signals2::signal<void(bool)>,
                       signals2::signal<void(bool)>,
                       signals2::signal<void(int, int)>,
                       signals2::signal<void(int, int)> > signal_map_t;
 
   signal_map_t signal_map;
};
 
template < class Sender >
struct Connector : public Sender
{
   template <size_t SignalID, class Slot>
   void connect(Slot slot)
   {
       std::get<SignalID>(this->signal_map).connect(slot);
       std::cout << "signal " << SignalID << " connected" << std::endl;
   }
};
 
template < class Sender >
struct Disconnector : public Sender
{
   template <size_t SignalID, class Slot>
   void disconnect(Slot slot)
   {
       std::get<SignalID>(this->signal_map).disconnect(slot);
       std::cout << "signal " << SignalID << " disconnected" << std::endl;
   }
};
 
template < size_t SignalID, class Sender, class Slot >
void connect(Sender &sender, Slot slot)
{
  typedef Connector<Sender> Connector;
  Connector &connector = static_cast<Connector &>(sender);
  connector.connect<SignalID>(slot);
}
 
template < size_t SignalID, class Sender, class Slot >
void disconnect(Sender &sender, Slot slot)
{
  typedef Disconnector<Sender> Disconnector;
  Disconnector &disconnector = static_cast<Disconnector &>(sender);
  disconnector.disconnect<SignalID>(slot);
}
 
void func(bool value)
{
   std::cout << "func " << value << std::endl;
}
 
int main()
{
   Demo demo;
 
   connect<Demo::visibleChanged>(demo, &func);
   demo.test();
   disconnect<Demo::visibleChanged>(demo, &func);
   demo.test();
 
   return 0;
}
 

При таком использовании Connector и Disconnector есть что-нибудь ужасное с точки зрения концепций ООП Улыбающийся (я правда, серьёзно спрашиваю), или какие другие подводные камни? Появляются ли накладные расходы по памяти/времени в runtime?
Записан

Пока сам не сделаешь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #68 : Октябрь 19, 2015, 22:59 »

Цитировать
Нужно продвинуться дальше, с наследованием. Допустим мы смирились с перечислением индексов сигналов в enum и их определением в tuple. Я правильно понимаю, что эти все connect, disconnect, emit придётся копипастить в каждый класс, где объявляются сигналы?
Нет, ну можно назвать класс Demo базовым. Т.е. сейчас можно запросто наследоваться от него и ничего копипастить не нужно, т.е.:
Код
C++ (Qt)
struct Derived : public Demo
{};
 
int main()
{
   Derived derived;
   derived.connect<Demo::visibleChanged>(&func); // or derived.connect<Derived::visibleChanged>(&func);
   derived.emit<Derived::visibleChanged>(true);
 
}
 

Или  речь идёт о том, что в наследниках нужно определять дополнительные сигналы (которых нет в базовом)?  

Цитировать
При таком использовании Connector и Disconnector есть что-нибудь ужасное с точки зрения концепций ООП  Улыбающийся (я правда, серьёзно спрашиваю), или какие другие подводные камни? Появляются ли накладные расходы по памяти/времени в runtime?
Мне кажется это уже перебор.. 
И я не совсем понимаю, какой сейчас от них профит?
« Последнее редактирование: Октябрь 19, 2015, 23:10 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #69 : Октябрь 19, 2015, 23:28 »

Или  речь идёт о том, что в наследниках нужно определять дополнительные сигналы (которых нет в базовом)?  

Да, в наследниках могут быть свои сигналы.
Записан

Пока сам не сделаешь...
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2094



Просмотр профиля
« Ответ #70 : Октябрь 20, 2015, 00:08 »

Цитировать
Да, в наследниках могут быть свои сигналы.
Ну тогда я бы особо не парился и сделал бы как Old предложил..
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #71 : Октябрь 20, 2015, 00:55 »

Ну тогда я бы особо не парился и сделал бы как Old предложил..

Хорошо, я понял Улыбающийся. В любом случае, спасибо за предложенный вариант Улыбающийся.
Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #72 : Октябрь 20, 2015, 09:29 »

Замечательно Улыбающийся. Теперь спрячьте определение сигнала в разделе protected и обеспечьте возможность подключаться/отключаться к ним любому желающему.
Есть правило "один топик - одна тема". На Ваш вопрос "буст сигнал+защита" ответ дан исчерпывающий. Теперь Вы хотите обсуждать др вещи (удобство и.т.п.) - почему бы и нет, но надо ясно сказать что это уже другое. А не ссылаться на то на что уже дан ответ. Насколько я понял, теперь Вы хотите так:

- есть базовый класс к которому можно (динамически, в рантайм) добавить любой бустовский сигнал, удалить, сделать connect/disconnect и эмиттить этот сигнал (учитывая protected/private). Верно?

Заметим что отказавшись от Qt сигналов Вы по-прежнему следуете Qt идеологии.
Записан
ViTech
Гипер активный житель
*****
Offline Offline

Сообщений: 858



Просмотр профиля
« Ответ #73 : Октябрь 20, 2015, 10:44 »

Есть правило "один топик - одна тема". На Ваш вопрос "буст сигнал+защита" ответ дан исчерпывающий. Теперь Вы хотите обсуждать др вещи (удобство и.т.п.) - почему бы и нет, но надо ясно сказать что это уже другое. А не ссылаться на то на что уже дан ответ.
Какой ответ в этой теме Вы считаете "исчерпывающим" для задачи, поставленной в первом сообщении? Его можно назвать единственно верным и оптимальным, исключающим появления лучших вариантов?

Насколько я понял, теперь Вы хотите так:
- есть базовый класс к которому можно (динамически, в рантайм) добавить любой бустовский сигнал, удалить, сделать connect/disconnect и эмиттить этот сигнал (учитывая protected/private). Верно?
Неверно Улыбающийся. Я хочу не более того, что задано в первом сообщении. Там есть конкретный пример, аналог которого меня интересует. В нём никакие сигналы динамически не добавляются. И мне даже интересно, после каких моих слов Вы решили, что я захотел такое динамическое поведение в рантайм? Улыбающийся

Заметим что отказавшись от Qt сигналов Вы по-прежнему следуете Qt идеологии.

Об этом можно поподробнее Улыбающийся. Какой Qt идеологии я следую?
« Последнее редактирование: Октябрь 20, 2015, 11:03 от ViTech » Записан

Пока сам не сделаешь...
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #74 : Октябрь 20, 2015, 13:11 »

Там есть конкретный пример, аналог которого меня интересует. В нём никакие сигналы динамически не добавляются. И мне даже интересно, после каких моих слов Вы решили, что я захотел такое динамическое поведение в рантайм? Улыбающийся
А почему? Если сигнал - переменная, то кто нам может помешать доливать их в рантайме? Правда не знаю как это сделать, типы-то разные. Но по-моему это интересно и небезвыгодно - хотя бы не отягощаем никого "классовостью", множ наследование - пожалуйста.

Об этом можно поподробнее Улыбающийся. Какой Qt идеологии я следую?
Да всей, поскольку ничего нового не видно. Также лепите сигналы-члены класса, коннект - по объектам и.т.п. Только вместо готового сервиса в Qt - пучина мутных темплейтов. Ну и за что боролись?
Записан
Страниц: 1 ... 3 4 [5] 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.161 секунд. Запросов: 22.