命名空间
变体
操作

std::variant

来自 cppreference.com
< cpp‎ | utility
 
 
实用程序库
语言支持
类型支持 (基本类型,RTTI)
库特性测试宏 (C++20)
动态内存管理
程序实用程序
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三方比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用实用程序
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (在 C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
通用词汇类型
(C++11)
(C++17)
(C++17)
variant
(C++17)
(C++11)
(C++17)
(C++23)
基本字符串转换
(C++17)
(C++17)

 
 
定义在头文件 <variant>
template< class... Types >
class variant;
(自 C++17 起)

类模板 std::variant 表示一个类型安全的 联合。在任何给定时间,std::variant 的实例要么包含其备用类型之一的值,要么在错误的情况下不包含任何值(此状态很难实现,请参见 valueless_by_exception)。

与联合一样,如果变体包含某个对象类型 T 的值,则 T 对象 嵌套在 variant 对象本身中。不允许变体分配额外的(动态)内存。

变体不允许包含引用、数组或类型 void

变体允许多次包含相同类型,并包含相同类型的不同 cv 限定版本。

与联合在 聚合初始化 期间的行为一致,默认构造的变体包含其第一个备用类型的值,除非该备用类型不可默认构造(在这种情况下,变体本身也不可默认构造)。辅助类 std::monostate 可用于使此类变体可默认构造。

使用没有模板参数的实例化 std::variant 定义的程序格式错误。可以使用 std::variant<std::monostate> 代替。

如果程序声明了 std::variant显式部分 特化,则该程序格式错误,不需要诊断。

内容

[编辑] 模板参数

类型 - 可以在此变体中存储的类型。所有类型都必须满足 可销毁 要求(特别是,不允许数组类型和非对象类型)。

[编辑] 成员函数

构造 variant 对象
(公共成员函数) [编辑]
销毁 variant,以及其包含的值
(公共成员函数) [编辑]
分配 variant
(公共成员函数) [编辑]
观察者
返回 variant 所包含的备用类型的零基索引
(公共成员函数) [编辑]
检查 variant 是否处于无效状态
(公共成员函数) [编辑]
修改器
variant 中就地构造一个值
(公共成员函数) [编辑]
与另一个 variant 交换
(公共成员函数) [编辑]
访问
(C++26)
使用 variant 所包含的参数调用提供的函数对象
(公共成员函数) [编辑]

[编辑] 非成员函数

(C++17)
使用一个或多个 variant 所包含的参数调用提供的函数对象
(函数模板) [编辑]
检查 variant 是否当前包含给定类型
(函数模板) [编辑]
根据索引或类型(如果类型是唯一的)读取变体的值,在错误时抛出异常
(函数模板) [编辑]
(C++17)
获取指向指向的 `variant` 的值的指针,根据索引或类型(如果唯一),在错误时返回空指针
(函数模板) [编辑]
(C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)
将 `variant` 对象与其包含的值进行比较
(函数模板) [编辑]
专门化了 std::swap 算法
(函数模板) [编辑]

[编辑] 辅助类

(C++17)
占位符类型,用作不可默认构造的类型的 `variant` 中的第一个备选方案
(类) [编辑]
在对 `variant` 的值进行无效访问时抛出的异常
(类) [编辑]
在编译时获取 `variant` 的备选方案列表的大小
(类模板) (变量模板)[编辑]
在编译时获取由索引指定的备选方案的类型
(类模板) (别名模板)[编辑]
std::variant 的哈希支持
(类模板专门化) [编辑]

[编辑] 辅助对象

`variant` 在无效状态下的索引
(常量) [编辑]

[编辑] 注释

功能测试 Std 功能
__cpp_lib_variant 201606L (C++17) std::variant: 类型安全的联合体
202102L (C++17)
(DR)
std::visit 用于从 std::variant 派生的类
202106L (C++20)
(DR)
完全 `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++ 标准。

DR 应用于 已发布的行为 正确行为
LWG 2901 C++17 提供了 std::uses_allocator 的专门化,
但 `std::variant` 不能正确支持分配器
专门化已移除
LWG 3990 C++17 程序可以声明 `std::variant` 的显式或
部分专门化
在这种情况下,程序是非法的(不需要诊断)
case (no diagnostic required)

[编辑] 另请参阅

就地构造标签
(标签)[编辑]
(C++17)
一个可能或不可能包含对象的包装器
(类模板) [编辑]
(C++17)
包含任何 CopyConstructible 类型的实例的对象
(类) [编辑]