網站首頁 編程語言 正文
一、說明語言擴展
以下庫擴展了編程語言 C++。
- Boost.Coroutine 使得在 C++ 中使用協程成為可能——其他編程語言通常通過關鍵字 yield 支持。
- Boost.Foreach 提供了一個基于范圍的 for 循環,它是在 C++11 中添加到語言中的。
- Boost.Parameter 允許您以名稱/值對的形式并以任何順序傳遞參數——例如,這在 Python 中是允許的。
- Boost.Conversion 提供了兩個轉換運算符來替換 dynamic_cast 并允許您區分向下轉換和交叉轉換。
二、庫Boost.Coroutine
通過 Boost.Coroutine,可以在 C++ 中使用協程。協程是其他編程語言的一個特性,通常使用關鍵字 yield 來表示協程。在這些編程語言中,yield 可以像 return 一樣使用。但是,當使用 yield 時,該函數會記住該位置,如果再次調用該函數,將從該位置繼續執行。
C++ 沒有定義關鍵字 yield。但是,使用 Boost.Coroutine 可以從函數返回并稍后從同一位置繼續。 Boost.Asio 庫也使用 Boost.Coroutine 并受益于協程。
三、示例和代碼
Boost.Coroutine 有兩個版本。本章介紹第二個版本,即當前版本。這個版本從 Boost 1.55.0 開始可用,并取代了第一個版本。
示例 51.1。使用協程
#include <boost/coroutine/all.hpp>
#include <iostream>
using namespace boost::coroutines;
void cooperative(coroutine<void>::push_type &sink)
{
std::cout << "Hello";
sink();
std::cout << "world";
}
int main()
{
coroutine<void>::pull_type source{cooperative};
std::cout << ", ";
source();
std::cout << "!\n";
}
Example51.1
示例 51.1 定義了一個函數 cooperative(),它作為協程從 main() 調用。 cooperative() 提前返回 main() 并被第二次調用。在第二次調用時,它會從中斷處繼續。
要將 cooperative() 用作協程,使用類型 pull_type 和 push_type。這些類型由 boost::coroutines::coroutine 提供,這是一個在示例 51.1 中用 void 實例化的模板。
要使用協程,您需要 pull_type 和 push_type。其中一種類型將用于創建一個對象,該對象將使用您想用作協程的函數進行初始化。另一種類型將是協程函數的第一個參數。
示例 51.1 在 main() 中創建了一個名為 source 的 pull_type 類型的對象。 cooperative() 傳遞給構造函數。 push_type 用作 cooperative() 簽名中的唯一參數。
創建源時,傳遞給構造函數的函數 cooperative() 會立即作為協程調用。發生這種情況是因為源基于 pull_type。如果源基于 push_type,則構造函數不會將 cooperative() 作為協程調用。
cooperative() 將 Hello 寫入標準輸出。之后,函數像訪問函數一樣訪問 sink 。這是可能的,因為 push_type 重載了 operator()。 main() 中的 source 表示協程 cooperative(),cooperative() 中的 sink 表示函數 main()。調用 sink 使 cooperative() 返回,而 main() 從調用 cooperative() 的地方繼續,并將逗號寫入標準輸出。
然后,main() 調用 source 就好像它是一個函數一樣。同樣,這是可能的,因為重載了 operator()。這一次,cooperative() 從中斷點繼續并將世界寫入標準輸出。因為 cooperative() 中沒有其他代碼,協程結束。它返回到 main(),它將一個感嘆號寫入標準輸出。
結果是示例 51.1 顯示 Hello, world!
您可以將協程視為協作線程。在某種程度上,函數 main() 和 cooperative() 同時運行。代碼在 main() 和 cooperative() 中輪流執行。每個函數內的指令按順序執行。多虧了協程,一個函數不需要在另一個函數執行之前返回。
示例 51.2。從協程返回一個值
#include <boost/coroutine/all.hpp>
#include <functional>
#include <iostream>
using boost::coroutines::coroutine;
void cooperative(coroutine<int>::push_type &sink, int i)
{
int j = i;
sink(++j);
sink(++j);
std::cout << "end\n";
}
int main()
{
using std::placeholders::_1;
coroutine<int>::pull_type source{std::bind(cooperative, _1, 0)};
std::cout << source.get() << '\n';
source();
std::cout << source.get() << '\n';
source();
}
Example51.2
示例 51.2 與前面的示例類似。這次模板 boost::coroutines::coroutine 是用 int 實例化的。這使得從協程返回一個 int 給調用者成為可能。
傳遞 int 值的方向取決于使用 pull_type 和 push_type 的位置。該示例使用 pull_type 在 main() 中實例化一個對象。 cooperative() 可以訪問 push_type 類型的對象。 push_type 發送一個值,pull_type 接收一個值;因此,設置了數據傳輸的方向。
cooperative() 調用 sink,參數類型為 int。此參數是必需的,因為協程是使用數據類型 int 實例化的。通過使用由 pull_type 提供的成員函數 get() 從 main() 中的 source 接收傳遞給 sink 的值。
示例 51.2 還說明了如何將具有多個參數的函數用作協程。 cooperative() 有一個額外的 int 類型參數,不能直接傳遞給 pull_type 的構造函數。該示例使用 std::bind() 將函數與 pull_type 鏈接起來。
該示例將 1 和 2 后跟 end 寫入標準輸出。
示例 51.3。將兩個值傳遞給協程
#include <boost/coroutine/all.hpp>
#include <tuple>
#include <string>
#include <iostream>
using boost::coroutines::coroutine;
void cooperative(coroutine<std::tuple<int, std::string>>::pull_type &source)
{
auto args = source.get();
std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n';
source();
args = source.get();
std::cout << std::get<0>(args) << " " << std::get<1>(args) << '\n';
}
int main()
{
coroutine<std::tuple<int, std::string>>::push_type sink{cooperative};
sink(std::make_tuple(0, "aaa"));
sink(std::make_tuple(1, "bbb"));
std::cout << "end\n";
}
Example51.3
示例 51.3 在 main() 中使用 push_type,在 cooperative() 中使用 pull_type,這意味著數據從調用方傳輸到協程。
此示例說明如何傳遞多個值。 Boost.Coroutine 不支持傳遞多個值,因此必須使用元組。您需要將多個值打包到元組或其他結構中。
示例 51.3 顯示 0 aaa、1 bbb 和 end。
示例 51.4。協程和異常
#include <boost/coroutine/all.hpp>
#include <stdexcept>
#include <iostream>
using boost::coroutines::coroutine;
void cooperative(coroutine<void>::push_type &sink)
{
sink();
throw std::runtime_error("error");
}
int main()
{
coroutine<void>::pull_type source{cooperative};
try
{
source();
}
catch (const std::runtime_error &e)
{
std::cerr << e.what() << '\n';
}
}
協程在拋出異常時立即返回。異常被傳輸到協程的調用者,在那里它可以被捕獲。因此,異常與常規函數調用沒有什么不同。
示例 51.4 顯示了這是如何工作的。此示例會將字符串錯誤寫入標準輸出。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127963272
相關推薦
- 2022-03-03 記一次瀏覽器SameSite策略更新,導致接口 Failed to load response da
- 2022-12-09 Android入門之ProgressBar的使用教程_Android
- 2022-03-07 golang強制類型轉換和類型斷言_Golang
- 2022-04-12 C++中的異常實例詳解_C 語言
- 2022-03-29 Android中的xml解析介紹_Android
- 2022-06-22 android使用intent傳遞參數實現乘法計算_Android
- 2023-10-16 Nginx啟動,重啟以及基本命令
- 2022-05-21 Python集合set()使用的方法詳解_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支