信号 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 类型的值
参考: