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时同时执行连接的几个方法。

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

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会对所有连接的方法进行调用,但是只会返回最后一个执行的结果。


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

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会操作绑定的方法

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();
}



你可能感兴趣的:(Signal,boost)