std::variant
來自 cppreference.com
定義於標頭檔案 <variant> |
||
template< class... Types > class variant; |
(C++17 起) | |
類模板 std::variant
表示一個型別安全的 聯合體。
variant
的例項在任何給定時間要麼持有一個其可選型別之一的值,要麼在發生錯誤時 - 不持任何值(這種狀態很難達到,參見 valueless_by_exception)。
與聯合體一樣,如果變體持有一個某種物件型別 T
的值,則 T
物件會巢狀在 variant
物件內。
變體不允許持有引用、陣列或 void 型別。
變體允許多次持有相同的型別,以及持有相同型別的不同 cv 限定版本。
與聯合體在聚合初始化期間的行為一致,預設構造的變體持有其第一個可選型別的值,除非該可選型別不可預設構造(在這種情況下,變體也不可預設構造)。輔助類 std::monostate 可以用於使此類變體可預設構造。
用無模板引數例項化 std::variant
定義的程式是病態的。可以改用 std::variant<std::monostate>。
如果程式聲明瞭 std::variant
的顯式或部分特化,則程式是病態的,無需診斷。
目錄 |
[編輯] 模板引數
型別 | - | 此變體中可能儲存的型別。所有型別都必須滿足 可析構 (Destructible) 要求(特別是,不允許陣列型別和非物件型別)。 |
[編輯] 成員函式
構造 variant 物件(公共成員函式) | |
銷燬 variant 及其包含的值(公共成員函式) | |
賦值一個 variant (公共成員函式) | |
觀察器 | |
返回 variant 所持可選型別的零基索引(公共成員函式) | |
檢查 variant 是否處於無效狀態(公共成員函式) | |
修改器 | |
在 variant 中原地構造一個值(公共成員函式) | |
與另一個 variant 交換(公共成員函式) | |
訪問(Visitation) | |
(C++26) |
使用 variant 持有的引數呼叫提供的函式物件(公共成員函式) |
[編輯] 非成員函式
(C++17) |
用一個或多個 variant 所持有的引數呼叫所提供的函式物件(函式模板) |
(C++17) |
檢查 variant 當前是否持有給定型別(函式模板) |
(C++17) |
根據索引或型別(如果型別唯一)讀取變體的值,出錯時丟擲異常 (函式模板) |
(C++17) |
根據索引或型別(如果唯一)獲取指向被指向 variant 值的指標,出錯時返回 null(函式模板) |
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20) |
將 variant 物件與其包含的值進行比較(函式模板) |
(C++17) |
特化 std::swap 演算法 (函式模板) |
[編輯] 輔助類
(C++17) |
用作非預設可構造型別變體的第一個替代項的佔位符型別 (類) |
(C++17) |
對 variant 的值進行無效訪問時丟擲的異常(類) |
(C++17) |
在編譯時獲取 `variant` 替代列表的大小 (類模板) (變數模板) |
在編譯時根據索引獲取可選型別的型別 (類模板) (別名模板) | |
(C++17) |
對 std::variant 的雜湊支援 (類模板特化) |
[編輯] 輔助物件
(C++17) |
無效狀態下 variant 的索引(常量) |
[編輯] 注意
特性測試宏 | 值 | 標準 | 特性 |
---|---|---|---|
__cpp_lib_variant |
201606L |
(C++17) | std::variant : 一個型別安全的聯合體 |
202102L |
(C++23) (DR17) |
用於從 std::variant 派生類的 std::visit | |
202106L |
(C++23) (DR20) |
完全 constexpr 的 std::variant | |
202306L |
(C++26) | 成員 visit |
[編輯] 示例
執行此程式碼
#include <cassert> #include <iostream> #include <string> #include <variant> int main() { std::variant<int, float> v, w; v = 42; // v contains int int i = std::get<int>(v); assert(42 == i); // succeeds w = std::get<int>(v); w = std::get<0>(v); // same effect as the previous line w = v; // same effect as the previous line // std::get<double>(v); // error: no double in [int, float] // std::get<3>(v); // error: valid index values are 0 and 1 try { std::get<float>(w); // w contains int, not float: will throw } catch (const std::bad_variant_access& ex) { std::cout << ex.what() << '\n'; } using namespace std::literals; std::variant<std::string> x("abc"); // converting constructors work when unambiguous x = "def"; // converting assignment also works when unambiguous std::variant<std::string, void const*> y("abc"); // casts to void const* when passed a char const* assert(std::holds_alternative<void const*>(y)); // succeeds y = "xyz"s; assert(std::holds_alternative<std::string>(y)); // succeeds }
可能的輸出
std::get: wrong index for variant
[編輯] 缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
缺陷報告 | 應用於 | 釋出時的行為 | 正確的行為 |
---|---|---|---|
LWG 2901 | C++17 | 提供了 std::uses_allocator 的特化, 但 variant 無法正確支援分配器 |
特化已移除 |
LWG 3990 | C++17 | 程式可以宣告 std::variant 的顯式或部分特化 |
在這種情況下程式是病態的 (無需診斷) |
LWG 4141 | C++17 | 對儲存的要求 令人困惑 |
包含的物件必須 巢狀在 variant 物件中 |
[編輯] 另請參見
原地構造標籤 (標籤) | |
(C++17) |
可能包含或不包含物件的包裝器 (類模板) |
(C++17) |
儲存任意 可複製構造 型別例項的物件 (類) |