boost::signal2笔记

     以前项目中作过一个功能就是根据一个数值变化来执行相应的策略,当时想到了订阅者设计模式,其中最关键的就是事件的关联和回溯,其实就是类型C#的委托和qt中的槽概念。原本用QT来实现又以为繁琐就选了一个比较普遍的库就用了boost的signals2功能.
所须要的头文件 :
      #include <boost/signal.hpp> 
建立第一个demo:
     下面的功能是实现建立一个signal的槽,而后咱们建立一个HelloWorld的结构体而后跟sig进行绑定,经过sig()方式能够直接调用全部与其绑定的方法。
struct HelloWorld { void operator()() const { std::cout << "Hello, World!" << std::endl; } };
 
boost::signal<void ()>sig;
int main(int argc, const char * argv[]) {
    HelloWorld helloworld;
    sig.connect(helloworld);
    sig();
  
    return 0;
}




链接多个事件:

     上面的demo实现的是一个方法的链接,下面是一个signal链接多个方法,而后当调用 sig时同时执行链接的几个方法。 ios

struct Hello{
    void operator()()const{
        std::cout<<"Hello ";
    }
};
struct World{
    void operator()()const{
        std::cout<<"World"<<std::endl;
    }
};
boost::signal<void ()>sig;
int main(int argc, const char * argv[]) {
 
    sig.connect(Hello());
    sig.connect(World());
    sig();
  
    return 0;
}




信号分组:
     除了上面的链接多个方法外,还能够将其进行分组,经过组号来决定执行的顺序。
sig.connect(1,Hello());
 sig.connect(0,World());
 sig();

上面的代码最终输出的World \n hello web

struct Hello{
    void operator()()const{
        std::cout<<"Hello ";
    }
};
struct World{
    void operator()()const{
        std::cout<<"World"<<std::endl;
    }
};
struct GoodMorning
{
    void operator()() const
    {
        std::cout << "... and good morning!" << std::endl;
    }
};
boost::signal<void ()>sig;
int main(int argc, const char * argv[]) {
 
    sig.connect(0,Hello());
    sig.connect(1,World());
    sig.connect(GoodMorning());
    sig();
  
    return 0;
}



在上面咱们添加了一个未分组的GoodMorning方法,咱们最终的输出结果将其插入到尾部,,其实咱们能够经过传入个
enum connect_position { at_back, at_front };默认为at_back

Slot参数

     除了上面的关联外还能够链接时传入参数,传入的参数会自动传送给全部链接的方法中。 设计模式

/
//  main.cpp
//  signals2
//
//  Created by wenchangshou on 15/11/17.
//  Copyright © 2015年 wenchangshou. All rights reserved.
//
 
#include <iostream>
#include <boost/signal.hpp> 
void print_args(float x, float y)
{
    std::cout << "The arguments are " << x << " and " << y << 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;
}
boost::signal<void (float,float)>sig;
int main(int argc, const char * argv[]) {
     
    sig.connect(&print_args);
    sig.connect(&print_sum);
    sig.connect(&print_product);
    sig.connect(&print_difference);
    sig.connect(&print_quotient);
     
    sig(5., 3.);
    return 0;
}



 输出结果:
The arguments are 5 and 3
The sum is 8
The product is 15
The difference is 2
The quotient is 1.66667
signal返回值:

     咱们不只能够传入参数也能够根据传入的参数的返回结果。 函数

#include <iostream>
#include <boost/signal.hpp> 
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; }
 
boost::signal<float (float,float)>sig;
int main(int argc, const char * argv[]) {
    sig.connect(&product);
    sig.connect(&quotient);
    sig.connect(&sum);
    sig.connect(&difference);
     
    std::cout<<sig(5., 3.)<<std::endl;
    return 0;
}



     上面的结果输出的为2,这是由于sig会对全部链接的方法进行调用,可是只会返回最后一个执行的结果。


     下面的例子是返回其中最大的数: spa

template<typename T>
struct maximum{
    typedef  T result_type;
    template<typename InputIterator>
    T operator()(InputIterator first,InputIterator last) const{
        if(first==last)return T();
        T max_value=*first++;
        while(first!=last){
            if(max_value<*first)
                max_value=*first;
            ++first;
        }
        return max_value;
    }
};
boost::signal<float (float,float),maximum<float>>sig;



     上面的是maximum就是一个Combiner,比较全部的结果返回最大数

     有的时候咱们但愿将全部槽的的返回结果放入一个组合当中 设计

template<typename Container>
struct aggregate_values{
    typedef  Container result_type;
    template<typename InputIterator>
    Container operator()(InputIterator first,InputIterator last) const{
        Container values;
        while(first!=last){
            values.push_back(*first);
            first++;
        }
        return values;
    }
};
   
std::vector<float> results=sig(5,3);
    std::copy(results.begin(), results.end(),
              std::ostream_iterator<float>(std::cout, " "));
    std::cout << "\n";




最终咱们会返回15 1.66667 8 2 
 disconnect();//取消槽链接
sig.connect(&foo);
  sig.connect(&bar);
  sig();

  // 取消foo而保留bar
  sig.disconnect(&foo);

下面的是模拟一个按照的操做,咱们定义了一个原型void(int x,int y),当咱们操做doOnClick时传入符合的函数签名时会进行链接,当调用 OnClick会操做绑定的方法 code

class Button
{
    typedef boost::signals2::signal<void (int x, int y)> OnClick;
public:
    typedef OnClick::slot_type OnClickSlotType;
    // 事件绑定,传入一个事件自动进行关系,传入的函数的定义OnClick;
    boost::signals2::connection doOnClick(const OnClickSlotType & slot);
     
    // 模拟用户的点击操做,输入坐标 52,38
    void simulateClick();
private:
    OnClick onClick;
};
 
boost::signals2::connection Button::doOnClick(const OnClickSlotType & slot)
{
    return onClick.connect(slot);
}
 
void Button::simulateClick()
{
    onClick(52, 38);
}
 
void printCoordinates(long x, long y)
{
    std::cout << "(" << x << ", " << y << ")\n";
}
 
//boost::signal<float (float,float),aggregate_values<vector<float>>>sig;
int main(int argc, const char * argv[]) {
    Button button;
    button.doOnClick(&printCoordinates);
    button.simulateClick();
}
相关文章
相关标签/搜索