用户类中的多重签名信号管理

发布于 2024-12-20 13:22:12 字数 2819 浏览 1 评论 0原文

我对 Qt 非常熟悉,并且我知道我们不能有类似的合成,因为我们这里没有 MOC 部分。然而,我试图在我的类中建立信号创建管理来简化信号的声明及其连接。

这大概就是我现在正在做的事情


    class Foo
    {
       public:
          void connectMove(boost::signal<void(int)>::slot_type slot)
          void connectRotate(boost::signal<void(double)>::slot_type slot)

       private:
          boost::signal<void(int)> m_signalMove;
          boost::signal<void(double)> m_signalRotate;
    };

,这基本上就是我想做的事情(大写=缺失部分)



    class SignalManager 
    {
       public:
          typedef boost::unrodered_map<std::string, GENERIC_SIGNAL *> MapSignal;
       public:
          template <typename Sig>
          bool connect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->connect(slot);
          }

          template <typename Sig>
          bool disconnect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->disconnect(slot);
          }

       protected:
          bool call(const std::string& strSignalName, SIGNAL_ARGS)
          {
             (*m_mapSignal.find(strSignalName))(SIGNAL_ARGS);
          }

          template <typename Sig>
          void delareSignal(const std::string& strSignalName)
          {
             m_mapSignals.insert(MapSignal::value_type(strSignalName, new boost::signal<Sig>()));
          }

          void destroySignal(const std::string& strSignalName)
          {
             // simplyfied... :
             auto it = m_mapSignal.find(strSignalName);
             delete *it;
             m_mapSignal.erase(it);
          }

       private:
          MapSignal m_mapSignals;
    };

    class Foo : public SignalManager
    {
       public:
          Foo(void)
          {
             this->declareSignal<void(int)>("Move");
             this->declareSignal<void(double)>("Rotate");
          }
    };


    class Other : public boost::signals::trackable
    {
       public:
          Other(Foo *p)
          {
             p->connect("Move", &Other::onMove);
             p->connect("Rotate", &Other::onRotate);
          }

          void onMove(int i)
          {
             /* ... */
          }

          void onRotate(double d)
          {
             /* ... */
          }
    };


我想我可以用 boost::functions_traits<> 解决“SIGNAL_ARGS”部分,但我不知道如何绕过抽象信号类型。

1/ 我想要的东西可能实现吗?

2/这是一个好方法吗? (我知道由于 unordered_map.find,我会产生一些开销,特别是当我使用 this->call("signalname", ...) 时,但我认为它不应该太重要)

3/如果这是不可能或不是一个好方法,您还有其他建议吗?

I'm very familiar with Qt and I know that we cannot have a similar synthax because we don't have the MOC part here. However I'm trying to have a signal creation management to simplify the declaration of a signal and the connection to it, inside my classes.

this is schematicly what I'm doing now


    class Foo
    {
       public:
          void connectMove(boost::signal<void(int)>::slot_type slot)
          void connectRotate(boost::signal<void(double)>::slot_type slot)

       private:
          boost::signal<void(int)> m_signalMove;
          boost::signal<void(double)> m_signalRotate;
    };

and this is basicaly what I would like to do (UPPERCASE = missing part)



    class SignalManager 
    {
       public:
          typedef boost::unrodered_map<std::string, GENERIC_SIGNAL *> MapSignal;
       public:
          template <typename Sig>
          bool connect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->connect(slot);
          }

          template <typename Sig>
          bool disconnect(const std::string& strSignalName, boost::signal<Sig>::slot_type slot)
          {
             // simplyfied... :
             (*m_mapSignal.find(strSignalName))->disconnect(slot);
          }

       protected:
          bool call(const std::string& strSignalName, SIGNAL_ARGS)
          {
             (*m_mapSignal.find(strSignalName))(SIGNAL_ARGS);
          }

          template <typename Sig>
          void delareSignal(const std::string& strSignalName)
          {
             m_mapSignals.insert(MapSignal::value_type(strSignalName, new boost::signal<Sig>()));
          }

          void destroySignal(const std::string& strSignalName)
          {
             // simplyfied... :
             auto it = m_mapSignal.find(strSignalName);
             delete *it;
             m_mapSignal.erase(it);
          }

       private:
          MapSignal m_mapSignals;
    };

    class Foo : public SignalManager
    {
       public:
          Foo(void)
          {
             this->declareSignal<void(int)>("Move");
             this->declareSignal<void(double)>("Rotate");
          }
    };


    class Other : public boost::signals::trackable
    {
       public:
          Other(Foo *p)
          {
             p->connect("Move", &Other::onMove);
             p->connect("Rotate", &Other::onRotate);
          }

          void onMove(int i)
          {
             /* ... */
          }

          void onRotate(double d)
          {
             /* ... */
          }
    };


I think I could resolve the "SIGNAL_ARGS" part with boost::functions_traits<>, but i don't know how to go around the abstract signal type.

1/ Is what I want even possible ?

2/ Is this a good approach ? (I know I will have some overhead due to the unordered_map.find, esspecily when I use this->call("signalname", ...), but I think it shouldn't be too significant)

3/ If this is not possible or not a good approach, do you have any other suggestions ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

疑心病 2024-12-27 13:22:12

我通过包装 boost::signals 并使用 boost::shared_ptr 而不是我的 GENERIC_SIGNAL 解决了我的问题。

参数问题也使用 boost::function_traits::arg_type 得到解决。

我不知道这是否是最好的方法,但它工作得很好,而且用户在继承此 SignalManager 的类中声明信号更加简单。

I resolved my problem by wrapping boost::signals and having a boost::shared_ptr<IWrapperSignal> instead of my GENERIC_SIGNAL.

The arguments probnlem was also resolved using boost::function_traits<T>::arg_type.

I don't know if it's the best way to do that, but it's working fine, and it is more simple for the user to declare signals in the classes that inherit this SignalManager.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文