【问题标题】:Signals2 connect() usage with templatesSignals2 connect() 与模板一起使用
【发布时间】:2013-08-22 16:59:26
【问题描述】:

我正在尝试为一些重复的功能创建模板类,这些功能将需要发送不同类型的数据。但是,我的问题(我认为)实际上是 InterfacePublisher::addSubscription() 函数使用 boost::signals2::signal::连接()

似乎 connect 函数正在获取基类的位置,即使派生类覆盖了它们。我确信会有一个解决方案,但现在我坚持了很长时间。

我在下面粘贴我的代码。这个想法是将字符串从 StringPublisher 传递到 StringSubscriber 而不通过模板对类名进行硬编码:

#include <string>
#include <iostream>

#include <boost/lambda/lambda.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/signals2/signal_base.hpp>
#include <boost/signals2/slot.hpp>
#include <boost/signals2/slot_base.hpp>

template <class T>
class InterfaceSubscriber
{
public:
    InterfaceSubscriber(const std::string& name)
        : mName         (name) {}

    virtual void onData (const std::string&   source, T& data)
    {
        std::cout << "InterfaceSubscriber::onData::BASE SHOULD BE IGNORED\n";
    }
protected:
    const std::string mName;
};




template <class T>
class InterfacePublisher
{
public:
    InterfacePublisher(const std::string& publisherName)
        : mPublisherName         (publisherName)
    {
    }

    void publish(T& data)
    {
        mSignalArgs(mPublisherName, data);
    }

    void addSubscription (InterfaceSubscriber<T>* subsc)
    {
        // The section where I think problem is. There is where the solution should be
        mSignalArgs.connect( std::bind (InterfaceSubscriber<T>::onData , *subsc, std::placeholders::_1, std::placeholders::_2) );
    }

protected:
    boost::signals2::signal<void (const std::string& publisherName, T& data)> mSignalArgs;
    const std::string mPublisherName;
};

class StringSubscriber : public InterfaceSubscriber<std::string>
{
public:
    StringSubscriber (const std::string& subscName) : InterfaceSubscriber(subscName) {}
    void onData (const std::string&   source, std::string&        data) override
    {
        std::cout << mName << ":[" << source << "]Received string of value: " << data << std::endl;
    }
};


class StringPublisher : public InterfacePublisher<std::string>
{
public:
    StringPublisher (const std::string& name) : InterfacePublisher(name) {}
};


int main()
{
    StringSubscriber subscriber1("String_Subscriber_1");
    StringSubscriber subscriber2("String_Subscriber_2");
    StringPublisher publisher("Publisher_Of_String");
    publisher.addSubscription(&subscriber1);
    publisher.addSubscription(&subscriber2);
    std::string str = "Hello World";

    // This should lead to StringSubscriber::onData being called, but instead ends up calling InterfaceSubscriber<T>::onData
    publisher.publish(str);

}

【问题讨论】:

    标签: c++ boost c++11 boost-signals2


    【解决方案1】:

    StringSubscriberstd::bind 仿函数的构造过程中被切片,导致InterfaceSubscriber&lt;T&gt;::onData() 在运行时类型为InterfaceSubscriber&lt;T&gt; 的对象上执行,而不是提供给InterfacePublisher&lt;T&gt;::addSubscription() 的对象的运行时类型。

    void addSubscription(InterfaceSubscriber<T>* subsc)
    {
      mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData, 
                                    *subsc, ...);
                                 // ^~~ sliced
    }
    

    要解决此问题,请直接传递指针或传递std::ref 对象作为实例。

    void addSubscription(InterfaceSubscriber<T>* subsc)
    {
      mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData,
                                    subsc, ...);
                                 // ^~~ pointer
    }
    

    void addSubscription(InterfaceSubscriber<T>* subsc)
    {
      mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData, 
                                    std::ref(*subsc), ...);
                                 // ^~~ reference
    }
    

    【讨论】:

    • 谢谢。以下行解决了我的问题:
      mSignalArgs.connect( std::bind (&InterfaceSubscriber::onData , std::ref(*subsc), std::placeholders::_1, std::placeholders: :_2));昨天我确实尝试了 std::ref 很多次,但我想我需要睡在上面!请注意“&”符号。
    • @BrainCracker:啊,是的,我没有可用的编译器,只是注意到了切片。使用适当的语法更新了答案。
    猜你喜欢
    • 2015-11-10
    • 2011-12-04
    • 2021-12-25
    • 2019-02-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 2016-12-28
    • 2021-08-08
    相关资源
    最近更新 更多