12.optional和variant
std::optional
表示 一个值 存在 或 不存在,给单个类型做“可空标记“。
头文件:<optional>
- 有值:存储一个
T类型对象 - 无值:空状态(
std::nullopt)
1. 基础应用场景
可以用作成员变量类型,类中某些属性可选但非必选,不用默认值占位(-1,0等特殊值标识无效),语义更清晰。
示例:
1 | class AgentMessage |
这是一个agent消息体的示例。
message_id_:必填消息唯一标识context_id_/task_id_:可选,代表上下文 ID、任务 ID,不存在则置std::nullopt
2. 判断是否有值
两种写法等价:
1 | if (opt1.has_value()) |
3. 取值
(1)value()
**无值时抛异常 std::bad_optional_access**,适合确定一定有值的场景。
1 | if (opt3) |
(2)解引用 *
和普通指针用法一致,空状态直接未定义行为(崩溃)
1 | if (opt3) |
(3)value_or(默认值)
为空时返回你指定的默认值,不会抛异常。
1 | int v = opt1.value_or(0); // 空 → 返回 0 |
std::variant<T1, T2, T3…>
同一时刻,只能存放模板参数列表中的「其中一种类型」,类型之间互斥,多种类型,多选一存储。
头文件:<variant>
类比:
- C 语言老式
union(联合体) std::variant= 类型安全的现代联合体
1. 使用场景
示例:A2A通信响应结构体,服务端返回的数据,**可能是任务对象 AgentTask,也可能是消息对象 AgentMessage**,这个类把两种结果包装到一起,对外提供统一的返回类型。
C++11兼容版:
1 | class A2AResponse |
同时持有两种实体,靠 type_ 区分当前有效数据。
std::variant版本:
1 | std::variant<AgentTask, AgentMessage> data; |
2. 构造与赋值
1 |
|
3. 判断当前是哪种类型
std::holds_alternative<类型>(变量)
返回 bool,判断当前存储的是不是指定类型。
1 | if (std::holds_alternative<int>(var)) |
4. 取值
std::get<类型>(变量)
按类型取出数据。
类型不匹配 → 抛异常 std::bad_variant_access。
1 | if (std::holds_alternative<int>(var)) |
补充:按索引取值
1 | // 模板参数 0 = 第一个类型 int |
5. 访问器:std::visit
统一遍历 / 处理 variant 内所有可能类型,代码更优雅。
1 | std::visit([](auto&& v) { |
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.