现在的位置: 首页 > 综合 > 正文

Boost signal 代码示例

2018年03月16日 ⁄ 综合 ⁄ 共 7534字 ⁄ 字号 评论关闭

网上介绍Boost signal原理的文章很多,这里不介绍原理,仅贴一些示例代码,这在初步接触Boost signal时能够有个较好的感性认识,深入了解需要去体会挖掘boost源码。代码基本上来自Boost turioal,其中有一些错误会导致编译不过,这里都做了更正:

1. 基本运用

#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace std;
using namespace boost;
struct HelloWorld
{
  void operator()() const
  {
    std::cout << "Hello, World!" << std::endl;
  }
};

struct HelloKitty
{
  void operator()() const
  {
    std::cout << "Hello, Kitty!" << std::endl;
  }
};
//
struct GoodMorning
{
      void operator()() const
      {
          std::cout << "... and good morning!" << std::endl;
      }
};

class Hello
{
    public:
        void print()
        {
            std::cout << "Hello, World!" << std::endl;
        }
};

class World : public boost::signals2::trackable
{
    public:
        void print()
        {
            std::cout << "Hello, World!" << std::endl;
        }
};

void print_hello()
{
    std::cout<<"Hello, world"<<std::endl;
}

void print_sum(float x, float y)
{
      std::cout << "The sum is " << x+y << std::endl;
}

void print_product(float x, float y)
{
      std::cout << "The product is " << x*y << std::endl;
}

void print_difference(float x, float y)
{
      std::cout << "The difference is " << x-y << std::endl;
}

void print_quotient(float x, float y)
{
      std::cout << "The quotient is " << x/y << std::endl;
}

float product(float x, float y) { return x*y; }
float quotient(float x, float y) { return x/y; }
float sum(float x, float y) { return x+y; }
float difference(float x, float y) { return x-y; }

template<typename T>
struct maximum
{
  typedef T result_type;

  template<typename InputIterator>
  T operator()(InputIterator first, InputIterator last) const
  {
    // If there are no slots to call, just return the
    // default-constructed value
    if (first == last)
      return T();

    T max_value = *first++;
    while (first != last) {
      if (max_value < *first)
        max_value = *first;
      ++first;
    }

    return max_value;
  }
};

template<typename Container>
struct aggregate_values
{
  typedef Container result_type;

  template<typename InputIterator>
  Container operator()(InputIterator first, InputIterator last) const
  {
    return Container(first, last);
  }
};


// Signal with no arguments and a void return value
int main()
{
    // Connect a HelloWorld slot
    HelloWorld hello;
    HelloKitty kitty;
    GoodMorning goodMorning;

    std::cout<<"****************sig1******************"<<std::endl;
    boost::signals2::signal<void ()> sig1;
    sig1.connect(1 ,hello);
    sig1.connect(0 ,kitty);
    sig1.connect(0 ,goodMorning);
    sig1();

    // Call all of the slots
    std::cout<<"****************sig2******************"<<std::endl;
    boost::signals2::signal<void (float, float) > sig2;
    sig2.connect(&print_product);
    sig2.connect(&print_quotient);
    sig2.connect(&print_sum);
    sig2.connect(&print_difference);
    sig2(5, 3);

    std::cout<<"****************sig3*******************"<<std::endl;
    boost::signals2::signal<float (float, float) > sig3;
    sig3.connect(product);
    sig3.connect(quotient);
    sig3.connect(sum);
    sig3.connect(difference);
    std::cout<< *sig3(5,3)<<std::endl;

    std::cout<<"****************sig4*******************"<<std::endl;
    boost::signals2::signal<float (float, float), maximum<float> > sig4;
    sig4.connect(product);
    sig4.connect(quotient);
    sig4.connect(sum);
    sig4.connect(difference);
    std::cout<< sig4(5,3)<<std::endl;

    std::cout<<"****************sig5*******************"<<std::endl;
    boost::signals2::signal<float (float, float), aggregate_values<std::vector<float> > > sig5;
    sig5.connect(product);
    sig5.connect(quotient);
    sig5.connect(sum);
    sig5.connect(difference);
    std::vector<float> results = sig5(5, 3);
    std::copy(results.begin(), results.end(), std::ostream_iterator<float>(cout, "\n"));

    std::cout<<"***************connection management connected**************"<<std::endl;
    boost::signals2::signal<void ()> sig6;
    boost::signals2::connection c = sig6.connect(HelloWorld());
    if (c.connected())
    {
        // c is still connected to the signal
        sig6(); // Prints "Hello, World!"
    }

    c.disconnect(); // Disconnect the HelloWorld object
    assert(!c.connected());
    sig6(); // Does nothing: there are no connected slots 

    std::cout<<"***************connection management block**************"<<std::endl;
    boost::signals2::signal<void ()> sig7;
    boost::signals2::connection c1 = sig7.connect(HelloWorld());
    sig7();
    {
        boost::signals2::shared_connection_block block(c1);
        sig7();
        std::cout<<"c1 is blocked"<<std::endl;
    }
    assert(!c1.blocked());
    sig7();

    std::cout<<"***************connection management scoped**************"<<std::endl;
    boost::signals2::signal<void ()> sig8;
    {
        boost::signals2::scoped_connection c2(sig8.connect(HelloWorld()));
        sig8();
        std::cout<<"c2 is blocked"<<std::endl;
    }
    sig8();

    std::cout<<"***************connection management connected**************"<<std::endl;
    boost::signals2::signal<void ()> sig9;
    sig9.connect(print_hello);
    sig9();
    std::cout<<"Disconnected sig9"<<std::endl;
    sig9.disconnect(print_hello);
    sig9();

    std::cout<<"***************connection management use shared_ptr**************"<<std::endl;
    boost::signals2::signal<void ()> sig10;
    {
        boost::shared_ptr<Hello> w(new Hello());
        sig10.connect(boost::bind(&Hello::print, w.get()));
    }

    std::cout <<"num of slots = "<< sig10.num_slots() << std::endl;
    sig10();

    std::cout<<"***************connection management use trackable**************"<<std::endl;
    boost::signals2::signal<void ()> sig11;
    {
        boost::shared_ptr<World> w(new World());
        sig11.connect(boost::bind(&World::print, w.get()));
    }

    std::cout <<"num of slots = "<< sig11.num_slots() << std::endl;
    sig11();


    return 0;
}


2.  综合运用

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

class NewsItem
{
public:
    NewsItem();

    NewsItem(const NewsItem& item)
    {
        msg = item.msg;
    }

    NewsItem(const std::string message)
    {
        msg = message;
    }

    const std::string text() const
    {
        return msg;
    }

private:
    std::string msg;
};

class MessageArea
{
public:
    MessageArea(){messageText = "default";}

    MessageArea(const MessageArea& messageArea)
    {
        messageText = messageArea.messageText;
    }

    MessageArea(const std::string  message)
    {
        messageText = message;
    }

    void update()
    {
        std::cout <<"messageText="<<messageText<<std::endl;
    }

    std::string messageText;
};

class NewsMessageArea : public MessageArea, public boost::signals2::trackable//trackable is important
{
public:
    NewsMessageArea(const std::string message):MessageArea(message){}
    void displayNews(const NewsItem& news)
    {
        messageText = news.text();
        update();
    }
};

int main()
{
    boost::signals2::signal<void (const NewsItem&) > deliverNews;
    NewsMessageArea* newsMessageArea = new NewsMessageArea("Hello, World!");
    deliverNews.connect(boost::bind(&NewsMessageArea::displayNews, newsMessageArea, _1));

    const NewsItem newItem("Hello, Kitty!");
    deliverNews(newItem);
   
    delete newsMessageArea;
    std::cout<<"*******Segmentation fault below if no trackable******"<<std::endl;
    deliverNews(newItem);

    return 0;
}

3. Boost Signal 运用于Documnet-View 模式

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

class Document
{
public:
    typedef boost::signals2::signal<void (bool)>  signal_t;
    typedef boost::signals2::connection  connection_t;

public:
    Document()
    {}

    connection_t connect(signal_t::slot_function_type subscriber)
    {
        return m_sig.connect(subscriber);
    }

    void disconnect(connection_t subscriber)
    {
        subscriber.disconnect();
    }

    void append(const char* s)
    {
        m_text += s;
        m_sig(true);
    }

    const std::string& getText() const
    {
        return m_text;
    }

private:
    signal_t    m_sig;
    std::string m_text;
};

class View
{
public:
    View(Document& m)
        : m_document(m)
    {
        m_connection = m_document.connect(boost::bind(&View::refresh, this, _1));
    }

    virtual ~View()
    {
        m_document.disconnect(m_connection);
    }

    virtual void refresh(bool bExtended) const = 0;

protected:
    Document&               m_document;

private:
    Document::connection_t  m_connection;
};

class TextView : public View
{
public:
    TextView(Document& doc)
        : View(doc)
    {}

    virtual void refresh(bool bExtended) const
    {
        std::cout << "TextView: " << m_document.getText() << std::endl;
    }
};

class HexView : public View
{
public:
    HexView(Document& doc)
        : View(doc)
    {}

    virtual void refresh(bool bExtended) const
    {
        const std::string&  s = m_document.getText();

        std::cout << "HexView:";

        for (std::string::const_iterator it = s.begin(); it != s.end(); ++it)
            std::cout << ' ' << std::hex << static_cast<int>(*it);

        std::cout << std::endl;
    }
};

int main(int argc, char* argv[])
{
    Document    doc;
    TextView    v1(doc);
    HexView     v2(doc);

    doc.append(argc == 2 ? argv[1] : "Hello world!");
    return 0;
}

另外这篇文章队Boost Signal的trackable特性有较为深入的分析,推荐大家可以参考下

http://www.cppblog.com/Error/archive/2014/05/30/207147.html

抱歉!评论已关闭.