std::variant
来自cppreference.com
                    
                                        
                    
                    
                                                            
                    |   定义于头文件  <variant>
  | 
||
|   template <class... Types> class variant;  | 
(C++17 起) | |
类模板 std::variant 表示一个类型安全的联合体。 std::variant 的一个实例在任意时刻要么保有其一个可选类型之一的值,要么在错误情况下无值(此状态难以达成,见 valueless_by_exception )。
与联合体在聚合初始化中的行为一致, 若 variant 保有某个对象类型 T 的值,则直接于 variant 的对象表示中分配 T 的对象表示。不允许 variant 分配额外的(动态)内存。
variant 不容许保有引用、数组,或类型 void 。空 variant 亦为病式(可用 std::variant<std::monostate> 代替)。
variant 容许保有同一类型多于一次,而且可保有同一类型的不同 cv 限定版本。
同联合体,默认构造的 variant 保有其首个选项的值,除非该选项不是可默认构造的(该情况下 variant 亦非可默认构造:能用辅助类 std::monostate 使这种 variant 可默认构造)。
模板形参
| Types | - |   可存储于此 variant 中的类型。所有类型必须满足可析构 (Destructible) 要求(特别是不允许数组类型和非对象类型)。
 | 
成员函数
  构造 variant 对象 (公开成员函数)  | |
  析构 variant 同其所含的值 (公开成员函数)  | |
  赋值 variant (公开成员函数)  | |
 观察器 | |
  返回 variant 所保有可选项的零基下标 (公开成员函数)  | |
  检查 variant 是否在非法状态 (公开成员函数)  | |
 修改器 | |
  原位构造 variant 中的值 (公开成员函数)  | |
   与另一 variant 交换 (公开成员函数)  | |
非成员函数
|    (C++17)  | 
  以一或多个 variant 所保有的各实参调用所提供的函数对象 (函数模板)  | 
|    (C++17)  | 
   检查某个 variant 是否当前持有某个给定类型 (函数模板)  | 
|    (C++17)  | 
  以给定索引或类型(若类型唯一)读取 variant 的值,错误时抛出异常  (函数模板)  | 
|    (C++17)  | 
  以给定索引或类型(若其唯一),获得指向被指向的 variant 的值的指针,错误时返回空指针  (函数模板)  | 
|    (C++17)(C++17)(C++17)(C++17)(C++17)(C++17)(C++20)  | 
  以所含值比较 variant 对象 (函数模板)  | 
|    (C++17)  | 
   特化 std::swap 算法  (函数)  | 
辅助类
|    (C++17)  | 
  用作非可默认构造类型的 variant 的首个可选项的占位符类型 (类)  | 
|    (C++17)  | 
  非法地访问 variant 的值时抛出的异常 (类)  | 
|    (C++17)  | 
  在编译时获得 variant 可选项列表的大小 (类模板) (变量模板)  | 
|    在编译时获得以其下标指定的可选项的类型   (类模板) (别名模板)  | |
|    (C++17)  | 
  特化 std::hash 算法   (类模板特化)  | 
辅助对象
|    (C++17)  | 
   非法状态的 variant 的下标 (常量)  | 
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| DR | 应用于 | 出版时的行为 | 正确行为 | 
|---|---|---|---|
| LWG 2901 | C++17 |  提供 std::uses_allocator 的特化,但 variant 不能正确支持分配器
 | 
移除特化 | 
示例
运行此代码
#include <variant> #include <string> #include <cassert> int main() { std::variant<int, float> v, w; v = 12; // v 含 int int i = std::get<int>(v); w = std::get<int>(v); w = std::get<0>(v); // 与前一行效果相同 w = v; // 与前一行效果相同 // std::get<double>(v); // 错误: [int, float] 中无 double // std::get<3>(v); // 错误:合法下标值为 0 与 1 try { std::get<float>(w); // w 含 int 而非 float :将抛出 } catch (const std::bad_variant_access&) {} using namespace std::literals; std::variant<std::string> x("abc"); // 转换构造函数在无歧义时起作用 x = "def"; // 转换赋值在无歧义时亦起作用 std::variant<std::string, void const*> y("abc"); // 传递 char const * 时转换成 void const * assert(std::holds_alternative<void const*>(y)); // 成功 y = "xyz"s; assert(std::holds_alternative<std::string>(y)); // 成功 }
 
参阅
|    原位构造标签   (类模板)  | |
|    (C++17)  | 
   可能或可能不保有一个对象的包装器   (类模板)  | 
|    (C++17)  | 
   可保有任何可复制构造 (CopyConstructible) 类型的实例的对象。  (类)  |