Signals-The Boost C++ Libraries
Signals-The Boost C++ Libraries
本文翻譯自Signals
Signals
Boost.Signals2
提供了boost::signals2::signal
類,可用於建立訊號。 此類在boost/signals2/signal.hpp
中定義。 或者,您可以使用標頭檔案boost/signals2.hpp
,它是一個主標頭檔案,定義了Boost.Signals2
中可用的所有類和函式。
Boost.Signals2
定義boost::signals2::signal
和其他類,以及名稱空間boost::signals2
中的所有函式。
示例67.1 “Hello,World” 使用boost::signals2::signal
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
signal<void()> s;
s.connect([]{ std::cout << "Hello, world!\n"; });
s();
}
boost::signals2::signal
是一個類别範本,它期望將用作事件處理程式的函式的簽名作為模板引數。 在例67.1中,只有具有void()
簽名的函式才能與訊號s關聯。
Lambda函式通過connect()
與訊號s關聯。 因為lambda函式符合所需的簽名void()
,所以成功建立了關聯。 每當訊號s觸發時,都會呼叫lambda函式。
像常規函式一樣通過呼叫來觸發訊號。 該函式的簽名與作為模板引數傳遞的簽名相匹配。 方括號為空,因為void()
不需要任何引數。 呼叫s會導致觸發器,該觸發器又執行先前與connect()
關聯的lambda函式。
例67.1也可以用std::function
實現,如例67.2所示。
示例67.2 “Hello,World!” 使用std::function
#include <functional>
#include <iostream>
int main()
{
std::function<void()> f;
f = []{ std::cout << "Hello, world!\n"; };
f();
}
在示例67.2
中,當呼叫f時,也會執行lambda函式。 雖然std::function
僅可用於示例67.2
之類的場景,但Boost.Signals2
提供了更多種類。 例如,它可以將多個功能與特定訊號關聯(請參見示例67.3
)。
示例67.3 使用boost::signals2::signal
的多個事件處理程式
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
signal<void()> s;
s.connect([]{ std::cout << "Hello"; });
s.connect([]{ std::cout << ", world!\n"; });
s();
}
boost::signals2::signal
允許您通過重複呼叫connect()
將多個功能分配給特定訊號。 無論何時觸發訊號,函式都會按照它們與connect()
關聯的順序執行。
還可以在connect()
的過載版本的幫助下顯式定義該順序,該版本期望將int
型別的值作為附加引數(示例67.4
)。
示例67.4 具有明確順序的事件處理程式
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
signal<void()> s;
s.connect(1, []{ std::cout << ", world!\n"; });
s.connect(0, []{ std::cout << "Hello"; });
s();
}
與前面的示例一樣,示例67.4
顯示Hello,world!
。
要從訊號中釋放關聯的函式,請呼叫disconnect()
。
示例67.5 斷開事件處理程式與boost::signals2::signal
的連線
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
void hello() { std::cout << "Hello"; }
void world() { std::cout << ", world!\n"; }
int main()
{
signal<void()> s;
s.connect(hello);
s.connect(world);
s.disconnect(world);
s();
}
示例67.5
僅輸出Hello,因為在觸發訊號之前已釋放了與world()
的關聯。
除了connect()
和disconnect()
外,boost:: signals2::signal
還提供了一些其他成員函式(請參見示例67.6
)。
示例67.6 boost::signals2::signal
的其他成員函式
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
signal<void()> s;
s.connect([]{ std::cout << "Hello"; });
s.connect([]{ std::cout << ", world!"; });
std::cout << s.num_slots() << '\n';
if (!s.empty())
s();
s.disconnect_all_slots();
}
num_slots()
返回關聯函式的數量。 如果沒有函式關聯,則num_slots()
返回0。empty()
告訴您是否連線了事件處理程式。 disconnect_all_slots()
的功能恰如其名:釋放所有現有的關聯。
示例67.7 處理事件處理程式的返回值
#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
signal<int()> s;
s.connect([]{ return 1; });
s.connect([]{ return 2; });
std::cout << *s() << '\n';
}
在示例67.7
中,兩個λ函式與訊號s相關聯。第一個lambda函式返回1,第二個返回2。
例67.7
將2
寫入標準輸出。 s正確接受了兩個返回值,但忽略了最後一個返回值。預設情況下,僅返回所有關聯函式的最後一個返回值。
請注意,s()
不會直接返回最後一個呼叫函式的結果。返回型別為boost::optional
的物件,取消引用後將返回數字2。觸發與任何功能均不相關的訊號不會產生任何返回值。因此,在這種情況下,boost::optional
允許Boost.Signals2
返回一個空物件。第21章介紹了boost::optional
。
可以自定義訊號,以便相應地處理各個返回值。為此,必須將組合器傳遞給boost::signals2::signal
作為第二個模板引數。
示例67.8 用使用者定義的組合器找到最小的返回值
#include <boost/signals2.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace boost::signals2;
template <typename T>
struct min_element
{
typedef T result_type;
template <typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
std::vector<T> v(first, last);
return *std::min_element(v.begin(), v.end());
}
};
int main()
{
signal<int(), min_element<int>> s;
s.connect([]{ return 1; });
s.connect([]{ return 2; });
std::cout << s() << '\n';
}
組合器是帶有過載operator()
的類。該操作符會被兩個迭代器自動呼叫,這兩個迭代器用於訪問與特定訊號關聯的功能。當取消迭代器的引用時,將呼叫函式,並且它們的返回值在組合器中變得可用。然後可以使用標準庫中的通用演算法(例如std::min_element()
)來計算並返回最小值(請參見示例67.8
)。
boost::signals2::signal
使用boost::signals2::optional_last_value
作為預設組合器。該組合器返回型別為boost::optional
的物件。使用者可以使用任何型別的返回值定義組合器。例如,示例67.8
中的組合器min_element
將作為模板引數傳遞的型別返回給min_element
。
無法將諸如std::min_element()
之類的演算法作為模板引數直接傳遞給boost::signals2::signal
。 boost::signals2::signal
期望組合器定義一個稱為result_type
的型別,該型別表示operato()
返回的值的型別。由於標準演算法未定義此型別,因此編譯器將報告錯誤。
請注意,不可能首先將迭代器直接傳遞到std::min_element()
,因為此演算法需要正向迭代器,而組合器則與輸入迭代器一起使用。這就是為什麼在使用std::min_element()
確定最小值之前,使用向量儲存所有返回值的原因。
例67.9
修改了組合器,以將所有返回值儲存在容器中,而不是對其求值。它將所有返回值儲存在一個向量中,然後由s()
返回。
示例67.9
使用使用者定義的合併器接收所有返回值
#include <boost/signals2.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace boost::signals2;
template <typename T>
struct return_all
{
typedef T result_type;
template <typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
return T(first, last);
}
};
int main()
{
signal<int(), return_all<std::vector<int>>> s;
s.connect([]{ return 1; });
s.connect([]{ return 2; });
std::vector<int> v = s();
std::cout << *std::min_element(v.begin(), v.end()) << '\n';
}
練習
建立帶有類button
的一個程式。 該類應表示圖形使用者介面中的按鈕。 新增成員函式·add_handler()和
remove_handler()都希望傳遞一個函式。 如果呼叫了另一個稱為
click()的成員函式,則應依次呼叫已註冊的處理程式。 例項化按鈕並通過註冊將訊息寫入標準輸出的處理程式來測試類。 呼叫
click()`以模擬滑鼠在按鈕上的單擊。
相關文章
- Ubuntu下安裝C++ boost庫UbuntuC++
- C++使用Boost多執行緒C++執行緒
- 一個C++ boost非同步socket serverC++非同步Server
- linux下使用boost.python呼叫c++動態庫LinuxPythonC++
- C++跨平臺庫boost和Poco的編譯C++編譯
- 簡單解析C++基於Boost庫實現命令列C++命令列
- C++霧中風景12:聊聊C++中的Mutex,以及拯救生產力的BoostC++Mutex
- boost library
- boost and windowsWindows
- C/C++利用Boost::Asio網路庫建立自己的Socket伺服器C++伺服器
- 超越C++標準庫:Boost庫導論電子書PDF下載C++
- cmake找不到boost
- Boost UDP Transaction PerformanceUDPORM
- Cannot dlopen some GPU libraries.GPU
- 安裝caffe時候找不到boost怎麼辦?(boost的引用問題make can‘t find Boost‘s include files)
- Flutter Boost3.0初探Flutter
- Swift Static Libraries遷移實踐Swift
- DYLD_INSERT_LIBRARIES的那些事
- pyav 是如何呼叫 FFmpeg libraries 的?
- Boost Your Strategy With The Content Marketing Tools
- buck電路 & boost電路
- boost http響應讀取HTTP
- Linux 中boost是什麼?Linux
- Boost 矩形布林運算
- MEV-Boost是什麼?
- 在Qt中使用boost庫QT
- 1、Dart : 建立併發布Dart Libraries;Dart
- 最新Turbo Boost Switcher Pro補丁破解版 Turbo Boost Switcher Pro破解安裝教程
- flutter_boost匯入問題Flutter
- Windows下下載編譯boost庫Windows編譯
- Flutter Boost 混合開發框架初探Flutter框架
- error while loading shared libraries: libclntsh.so.10.1ErrorWhile
- BOOST應用 無法解析的外部符號 "void __cdecl boost::throw_exception(class std::exception const &)"符號Exception
- Linux安裝boost、libevent、zlib、OpenSSL庫Linux
- Boost.Test 斷言的介紹
- 手把手教你實現boost::bind
- rocky9中boost的安裝
- 協程Part1-boost.Coroutine.md