应显式检查std::expected的.has_value()或用if语句解包,失败时通过.error()获取std::error_code并比对标准errc;写文件需将errno转为std::error_code(errno, std::generic_category())以支持跨平台错误码;优先用std::error_code而非std::string以保障类型安全与高效分支处理;注意C++23兼容性及各平台filesystem行为差异。

std::expected 读文件时怎么接住 std::filesystem::read_bytes 的失败?
它不抛异常,但会返回 std::expected<:vector>, std::error_code> —— 你得显式检查,不能当普通返回值用。
常见错误是直接解包:auto data = std::filesystem::read_bytes(path).value(),一旦路径不存在或权限不足,.value() 就 std::terminate。
- 必须先调用
.has_value()或用if (auto r = read_bytes(...)) { ... }检查成功分支 - 失败时,
r.error()是std::error_code,可直接比对std::errc::no_such_file_or_directory等标准枚举 -
std::filesystem::read_bytes在 Windows 上对某些符号链接或重解析点可能静默失败,建议搭配std::filesystem::status预检
写文件出错后,怎么用 std::expected 区分“磁盘满”和“只读文件系统”?
标准库没提供带 std::expected 的原子写入接口,得自己封装 std::ofstream 或 std::FILE* 调用。
关键不是“怎么封装”,而是错误码映射:C 库的 errno 值(如 ENOSPC、EROFS)必须转成 std::error_code 才能进 std::expected。
- 别用
std::make_error_code(std::errc::...)硬编码——那是 POSIX 错误码子集,ENOSPC对应std::errc::no_space_on_device,但EROFS不在std::errc里 - 更稳妥的是用
std::error_code(errno, std::generic_category())构造 - 写临时文件 +
std::filesystem::rename原子提交时,两个操作都要单独检查std::expected,不能只验 rename
为什么 std::expected 比 std::expected 更实用?
因为错误处理要分支,不是打日志。字符串没法 switch,也不能直接和 std::errc 比较,失去类型安全。
比如你想对“文件已存在”做覆盖逻辑,对“路径是目录”则报错退出,用 std::string 就只能 find("File exists"),脆弱又慢。
-
std::error_code支持==和.category(),能精准匹配std::errc::file_exists或std::errc::is_a_directory - 自定义错误类型(如
enum class io_errc)也能通过std::error_code(ec, my_category())接入同一套处理流程 - 传参/返回时,
std::error_code是轻量值类型;std::string有堆分配开销,且无法静态断言错误集合
跨平台编译时,std::expected 的兼容性陷阱在哪?
它从 C++23 才进标准,但 MSVC 19.35+、GCC 12.2+、Clang 16+ 已支持。问题不在语言特性,而在依赖的 std::filesystem 行为差异。
Windows 下 std::filesystem::read_bytes 可能因 UAC 或 OneDrive 同步状态返回不同 error_code;Linux 下 EACCES 和 EPERM 语义也不完全等价。
- 别假设
std::errc::permission_denied在所有平台都覆盖全部权限错误 - CI 测试必须跑在真实目标平台,不能只靠 WSL 或 Docker 模拟
- 如果项目需支持 C++20,别硬上
std::expected—— tl::expected 是更稳的选择,但注意其error_type构造语义和标准版略有不同
最易被忽略的是:std::expected 不改变底层系统调用的行为,它只帮你结构化地暴露错误。文件锁、NFS 缓存、杀毒软件拦截这些,依然得靠重试逻辑和超时控制,不是换个返回类型就能解决的。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











