網站首頁 編程語言 正文
一、提要
????????Boost.Variant 提供了一個類似于 union 的名為 boost::variant 的類。您可以將不同類型的值存儲在 boost::variant 變量中。在任何時候只能存儲一個值。分配新值時,舊值將被覆蓋。但是,新值的類型可能與舊值不同。唯一的要求是這些類型必須作為模板參數傳遞給 boost::variant,這樣它們才能為 boost::variant 變量所知。
????????boost::variant 支持任何類型。例如,可以將 std::string 存儲在 boost::variant 變量中——這在 C++11 之前使用聯合是不可能的。在 C++11 中,對聯合的要求被放寬了。現在聯合可以包含一個 std::string。因為 std::string 必須使用placement new 進行初始化,并且必須通過顯式調用析構函數來銷毀,所以使用 boost::variant 仍然有意義,即使在 C++11 開發環境中也是如此。
二、示例
????????示例 24.1。使用 boost::variant
#include <boost/variant.hpp>
#include <string>
int main()
{
boost::variant<double, char, std::string> v;
v = 3.14;
v = 'A';
v = "Boost";
}
????????boost::variant 在 boost/variant.hpp 中定義。因為 boost::variant 是一個模板,所以必須至少指定一個參數。一個或多個模板參數指定支持的類??型。在示例 24.1 中,v 可以存儲類型為 double、char 或 std::string 的值。但是,如果您嘗試將 int 類型的值分配給 v,則生成的代碼將無法編譯。
????????示例 24.2。使用 boost::get() 訪問 boost::variant 中的值
#include <boost/variant.hpp>
#include <string>
#include <iostream>
int main()
{
boost::variant<double, char, std::string> v;
v = 3.14;
std::cout << boost::get<double>(v) << '\n';
v = 'A';
std::cout << boost::get<char>(v) << '\n';
v = "Boost";
std::cout << boost::get<std::string>(v) << '\n';
}
????????要顯示 v 的存儲值,請使用獨立函數 boost::get()(參見示例 24.2)。
????????boost::get() 期望對應變量的有效類型之一作為模板參數。指定無效類型將導致運行時錯誤,因為類型驗證不會在編譯時進行。
????????boost::variant 類型的變量可以寫入標準輸出流等流,從而繞過運行時錯誤的風險(參見示例 24.3)。
????????示例 24.3。在流上直接輸出 boost::variant
#include <boost/variant.hpp>
#include <string>
#include <iostream>
int main()
{
boost::variant<double, char, std::string> v;
v = 3.14;
std::cout << v << '\n';
v = 'A';
std::cout << v << '\n';
v = "Boost";
std::cout << v << '\n';
}
????????對于類型安全的訪問,Boost.Variant 提供了一個名為 boost::apply_visitor() 的函數。
????????示例 24.4。使用訪問者來提升::variant
#include <boost/variant.hpp>
#include <string>
#include <iostream>
struct output : public boost::static_visitor<>
{
void operator()(double d) const { std::cout << d << '\n'; }
void operator()(char c) const { std::cout << c << '\n'; }
void operator()(std::string s) const { std::cout << s << '\n'; }
};
int main()
{
boost::variant<double, char, std::string> v;
v = 3.14;
boost::apply_visitor(output{}, v);
v = 'A';
boost::apply_visitor(output{}, v);
v = "Boost";
boost::apply_visitor(output{}, v);
}
????????作為其第一個參數,boost::apply_visitor() 期望從 boost::static_visitor 派生的類的對象。此類必須為它所作用的 boost::variant 變量使用的每種類型重載 operator()。因此,在示例 24.4 中,運算符重載了 3 次,因為 v 支持 double、char 和 std::string 類型。
????????boost::static_visitor 是一個模板。 operator() 的返回值類型必須指定為模板參數。如果運算符沒有返回值,則不需要模板參數,如示例中所示。
????????傳遞給 boost::apply_visitor() 的第二個參數是一個 boost::variant 變量。
????????boost::apply_visitor() 自動為第一個參數調用 operator() ,該參數與當前存儲在第二個參數中的值的類型相匹配。這意味著每次調用 boost::apply_visitor() 時,示例程序都會使用不同的重載運算符——首先是用于 double 的運算符,然后是用于 char 的運算符,最后是用于 std::string 的運算符。
????????boost::apply_visitor() 的優點不僅在于自動調用正確的運算符。此外,boost::apply_visitor() 確保為 boost::variant 變量支持的每種類型都提供了重載運算符。如果未定義三個重載運算符之一,則無法編譯代碼。
????????如果重載的運算符在功能上是等效的,則可以使用模板簡化代碼(參見示例 24.5)。
????????示例 24.5。使用帶有 boost::variant 函數模板的訪問者
#include <boost/variant.hpp>
#include <string>
#include <iostream>
struct output : public boost::static_visitor<>
{
template <typename T>
void operator()(T t) const { std::cout << t << '\n'; }
};
int main()
{
boost::variant<double, char, std::string> v;
v = 3.14;
boost::apply_visitor(output{}, v);
v = 'A';
boost::apply_visitor(output{}, v);
v = "Boost";
boost::apply_visitor(output{}, v);
}
????????因為 boost::apply_visitor() 確保了編譯時代碼的正確性,所以應該優先于 boost::get()。
原文鏈接:https://yamagota.blog.csdn.net/article/details/127339007
相關推薦
- 2022-09-30 Python使用draw類繪制圖形示例講解_python
- 2022-04-23 論C++的lambda是函數還是對象_C 語言
- 2022-09-02 useEffect支持async及await使用方式_React
- 2022-09-29 C++Vector容器常用函數接口詳解_C 語言
- 2022-10-07 C語言順序查找算法介紹及示例_C 語言
- 2022-05-21 基于C++實現酒店管理系統_C 語言
- 2022-08-11 Python操作數據庫之數據庫編程接口_python
- 2022-08-27 C#過濾sql特殊字符串的方法_C#教程
- 最近更新
-
- 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同步修改后的遠程分支