名稱空間
變體
操作

std::variant

來自 cppreference.com
< cpp‎ | 工具
 
 
 
 
定義於標頭檔案 <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 所持有的引數呼叫所提供的函式物件
(函式模板) [編輯]
檢查 variant 當前是否持有給定型別
(函式模板) [編輯]
根據索引或型別(如果型別唯一)讀取變體的值,出錯時丟擲異常
(函式模板) [編輯]
(C++17)
根據索引或型別(如果唯一)獲取指向被指向 variant 值的指標,出錯時返回 null
(函式模板) [編輯]
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)
variant 物件與其包含的值進行比較
(函式模板) [編輯]
特化 std::swap 演算法
(函式模板) [編輯]

[編輯] 輔助類

(C++17)
用作非預設可構造型別變體的第一個替代項的佔位符型別
(類) [編輯]
variant 的值進行無效訪問時丟擲的異常
(類) [編輯]
在編譯時獲取 `variant` 替代列表的大小
(類模板) (變數模板)[編輯]
在編譯時根據索引獲取可選型別的型別
(類模板) (別名模板)[編輯]
std::variant 的雜湊支援
(類模板特化) [編輯]

[編輯] 輔助物件

無效狀態下 variant 的索引
(常量) [編輯]

[編輯] 注意

特性測試 標準 特性
__cpp_lib_variant 201606L (C++17) std::variant: 一個型別安全的聯合體
202102L (C++23)
(DR17)
用於從 std::variant 派生類的 std::visit
202106L (C++23)
(DR20)
完全 constexprstd::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)
儲存任意 可複製構造 型別例項的物件
(類) [編輯]