std::optional是C++17引入的标准库类型,用于安全地表示一个可能不存在的值,避免直接使用裸指针或特殊值标记空状态的弊端。and_then和or_else是std::optional提供的两个单体操作接口,能够大幅简化对optional值的后续处理逻辑。
and_then接口的作用与用法
and_then接口仅在std::optional持有有效值的时候被调用,它会接收一个返回std::optional类型的可调用对象,将当前持有的值作为参数传入该对象,最终返回可调用对象的返回结果。
如果std::optional当前不持有值,and_then会直接返回空的std::optional,不会执行传入的可调用对象。
基础使用示例
下面的代码展示了and_then的基本用法,实现将字符串转换为整数后,再对整数做加一操作的逻辑:
#include <optional>
#include <string>
#include <iostream>
// 将字符串转换为整数,转换失败返回空optional
std::optional<int> str_to_int(const std::string& s) {
try {
return std::stoi(s);
} catch (...) {
return std::nullopt;
}
}
// 对整数加一,返回新的optional
std::optional<int> add_one(int num) {
return num + 1;
}
int main() {
std::optional<std::string> str_opt = "123";
// 先转换字符串到整数,再对整数加一
auto result = str_opt.and_then(str_to_int).and_then(add_one);
if (result.has_value()) {
std::cout << "最终结果:" << result.value() << std::endl;
} else {
std::cout << "处理失败" << std::endl;
}
return 0;
}
or_else接口的作用与用法
or_else接口仅在std::optional不持有有效值的时候被调用,它会接收一个无参数且返回同类型std::optional的可调用对象,执行该对象后返回其结果。
如果std::optional当前持有有效值,or_else会直接返回当前optional,不会执行传入的可调用对象。
基础使用示例
下面的代码展示了or_else的基本用法,当字符串转换失败时提供默认值:
#include <optional>
#include <string>
#include <iostream>
std::optional<int> str_to_int(const std::string& s) {
try {
return std::stoi(s);
} catch (...) {
return std::nullopt;
}
}
int main() {
std::optional<std::string> str_opt = "abc"; // 无效字符串
// 转换失败时使用默认值10
auto result = str_opt.and_then(str_to_int).or_else([]{
return std::optional<int>(10);
});
std::cout << "结果值:" << result.value() << std::endl;
return 0;
}
and_then与or_else的链式用法
and_then和or_else可以结合使用,实现完整的optional值处理链路:先尝试对有效值做一系列转换操作,若任意一步失败则执行兜底逻辑。
链式调用示例
下面的代码实现了一个完整的处理链路:解析字符串到整数,验证整数范围,对整数做平方运算,若任意步骤失败则返回默认结果:
#include <optional>
#include <string>
#include <iostream>
// 字符串转整数
std::optional<int> str_to_int(const std::string& s) {
try {
return std::stoi(s);
} catch (...) {
return std::nullopt;
}
}
// 验证整数是否在1到100之间
std::optional<int> validate_range(int num) {
if (num >= 1 && num <= 100) {
return num;
}
return std::nullopt;
}
// 计算整数平方
std::optional<int> square(int num) {
return num * num;
}
int main() {
// 测试有效输入
std::optional<std::string> valid_input = "20";
auto valid_result = valid_input
.and_then(str_to_int)
.and_then(validate_range)
.and_then(square)
.or_else([]{
return std::optional<int>(0); // 失败返回0
});
std::cout << "有效输入结果:" << valid_result.value() << std::endl;
// 测试无效输入
std::optional<std::string> invalid_input = "200";
auto invalid_result = invalid_input
.and_then(str_to_int)
.and_then(validate_range)
.and_then(square)
.or_else([]{
return std::optional<int>(0); // 失败返回0
});
std::cout << "无效输入结果:" << invalid_result.value() << std::endl;
return 0;
}
使用注意事项
- and_then传入的可调用对象必须返回std::optional类型,否则会导致编译错误
- or_else传入的可调用对象不能接收参数,且返回类型必须和当前optional的类型一致
- 链式调用中每一步的optional类型需要保持兼容,避免类型不匹配的问题
- 如果不需要返回新的optional,仅需要执行副作用操作,可以使用
std::optional::transform或者std::optional::if_present接口,这两个接口不属于单体操作模式,但常和and_then、or_else配合使用
通过合理使用and_then和or_else的链式调用,可以替代大量的if-else判断逻辑,让代码更简洁,也更符合函数式编程的风格,同时避免空值访问带来的未定义行为。
std_optionaland_thenor_elseC++单体操作修改时间:2026-07-20 11:45:32