boost库学习:事件处理

信号 Signals

信号总是与信号处理器联系在一起,或者说,事件总是绑定到用于处理它的事件处理器中。

简单使用

#include <boost/signals2/signal.hpp> // 旧的库可能是 #include <boost/signal.hpp> 
#include <iostream>

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

int func1(int num)
{
  std::cout << num << std::endl;
}

int main()
{
  boost::signals2::signal<void ()> s; // 旧的库可能是boost::signal<void ()> s;
  boost::signals2::signal<int (int)> s2;
  s.connect(func);
  s2.connect(func1);
  s();
  s2(1);
}

以上代码将信号s关联到处理函数func。

boost::signal 是一个模板函数,模板参数是所关联函数的签名,以上定义,指定了void()形式的函数才能绑定到信号s;如果signal定义的模板参数形式和connect的参数对应函数签名不一致,或者s调用的方式与func定义不一致,都会报错。

当信号s被触发时(调用s()),函数func将被调用。注意connect的参数func是不带括号的。

与 boost::function 区别

以上代码功能用 boost::function 也能实现,但是 boost::function 只能实现一一绑定,而 signal 则可以实现一对多关系

多个函数绑定到一个信号

#include <boost/signals2/signal.hpp> 
#include <iostream> 

void func1() 
{ 
  std::cout << "first" << std::endl; 
} 

void func2() 
{ 
  std::cout << "second" << std::endl; 
} 

int main() 
{ 
  boost::signals2::signal<void ()> s; 
  //s.connect(func1); 
  //s.connect(func2);
  // 按照关联的顺序调用 
  //s(); 
  
  s.connect(1, func1); 
  s.connect(0, func2);                                         
  // 按照第一个参数指定优先级,值越小越优先 不连续也可以
  s();
} 

以上代码将信号s绑定到func1和func2,如果是 s.connect(func1) 的绑定方式,则按connect顺序调用函数;如果是 s.connect(1, func1); 的方式,则根据第一个参数(1)指定优先级调用函数,值越小越优先(不连续的值也可以,例如以下代码)。

 s.connect(3, func1); 
 s.connect(1, func2);   

如果有兴趣还可以这样:

boost::signals2::signal<void ()> s;
s.connect(func1);
s.connect(func2);
s.connect(func1);
s.connect(func2);
s.connect(2, func1);
s.connect(3, func1);
s.connect(5, func2);
s();

看看有没有什么发现,我还没看出啥规律……

将信号与函数解绑

#include <boost/signals2/signal.hpp>                           
#include <iostream>

void func1()
{
  std::cout << "first" << std::endl;
}

void func2()
{
  std::cout << "second" << std::endl;
}

int main()
{
  boost::signals2::signal<void ()> s;
  s.connect(func1);
  s.connect(func2);
  std::cout << "conn num:" << s.num_slots() << std::endl; // 已关联函数数量
  std::cout << "empty:" << s.empty() << std::endl; // 是否没有任何关联
  s.disconnect(func2);  // 释放func2的关联
  std::cout << "conn num:" << s.num_slots() << std::endl;
  std::cout << "empty:" << s.empty() << std::endl;
  s.disconnect_all_slots(); // 释放所有关联
  std::cout << "conn num:" << s.num_slots() << std::endl;
  std::cout << "empty:" << s.empty() << std::endl;
}
                                                               

相关函数有:disconnect、num_slots、empty、disconnect_all_slots

函数返回值

如果信号绑定了两个函数,且两个函数都有返回值,那么信号触发的结果输出到标准输出流,将会是最后一个函数的返回值。

#include <boost/signals2/signal.hpp>                                                                                                                                          
#include <iostream>

int func1()
{
  return 1;
}

int func2()
{
  return 2;
}

int main()
{
  boost::signals2::signal<int ()> s;
  s.connect(func1);
  s.connect(func2);
  std::cout << s().value() << std::endl;  // 参考教程直接调用s()会报错,可能是版本问题,根据错误信息找到boost源码,查看 boost/optional/optional.hpp 文件result_type 的接口即可
}

结果输出2

合成器

如果需要对已绑定所有函数的返回值都处理,则需要定义合成器,并将其实例作为第二个参数传递给 boost::signals2::signal

#include <boost/signals2/signal.hpp> 
#include <iostream> 
#include <algorithm> 

int func1() 
{ 
  return 1; 
} 
int func2() 
{ 
  return 2; 
} 

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

  template <typename InputIterator> 
  T operator()(InputIterator first, InputIterator last) const 
  { 
    return *std::max_element(first, last); 
  } 
}; 

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

int main() 
{ 
  boost::signals2::signal<int (), max_element<int> > s; 
  boost::signals2::signal<int (), maximum<int> > s2; 
  s.connect(func1); 
  s2.connect(func1); 
  s.connect(func2); 
  s2.connect(func2);  
  std::cout << s() << std::endl; 
  std::cout << s2() << std::endl; 

} 

以上代码 max_element 的输出和预想的不符,还没看出问题……

合成器也可以保存所有返回结果

#include <boost/signals2/signal.hpp>                                 
#include <iostream>
#include <algorithm>
#include <vector>

int func1()
{
  return 1;
}
int func2()
{
  return 2;
}

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

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

int main()
{
  boost::signals2::signal<int (), maximum<std::vector<int> > > s2;
  s2.connect(func1);
  s2.connect(func2);
  std::vector<int> v = s2();
  std::cout << v.size() << std::endl;
}

连接 Connections

boost::signals::connection 类型

 connect() 会返回一个 boost::signals::connection 类型的值

参考:

Boost C++ 库 第 4 章 事件处理

官方文档

猜你喜欢

转载自blog.csdn.net/guangyacyb/article/details/86027683