编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第15章_错误处理.cpp -o t && ./t(需先 cd 测试/)
// 第15章测试:错误处理
#include <print>
#include <stdexcept>
#include <optional>
#include <expected>
#include <string>
#include <vector>
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
// 15.2 异常版除法
double divide_throw(double a, double b) {
if (b == 0.0) throw std::invalid_argument("除数不能为 0");
return a / b;
}
// 15.6 expected 版除法
enum class DivErr { DivZero, Neg };
std::expected<double, DivErr> divide_expected(double a, double b) {
if (b == 0.0) return std::unexpected(DivErr::DivZero);
return a / b;
}
// 15.6 optional 版:从 vector 找第一个偶数
std::optional<int> first_even(const std::vector<int>& v) {
for (int x : v)
if (x % 2 == 0) return x;
return std::nullopt;
}
// 15.4 noexcept:移动操作
struct Movable {
std::string data;
Movable() = default;
Movable(Movable&& other) noexcept
: data(std::move(other.data)) {}
Movable& operator=(Movable&& other) noexcept {
data = std::move(other.data);
return *this;
}
};
int main() {
// 15.2 异常捕获
try {
double r = divide_throw(1.0, 0.0);
(void)r;
CHECK(false); // 不该到这里
} catch (const std::invalid_argument& e) {
CHECK(std::string(e.what()) == "除数不能为 0");
}
CHECK(divide_throw(8.0, 2.0) == 4.0);
// 15.3 异常传播(c 抛 → main 接)
try {
std::vector<int>().at(5); // 越界 → out_of_range
CHECK(false);
} catch (const std::out_of_range& e) {
CHECK(true);
}
// 15.5 异常不发生时开销为零路径也正常
for (int i = 0; i < 1000; ++i) {
CHECK(divide_throw(1.0, 2.0) == 0.5);
}
// 15.6 expected 用法
auto ok = divide_expected(10.0, 4.0);
CHECK(ok && *ok == 2.5);
auto bad = divide_expected(1.0, 0.0);
CHECK(!bad && bad.error() == DivErr::DivZero);
CHECK(ok.value_or(-1.0) == 2.5);
auto scaled = ok.transform([](double x) { return x * 2; });
CHECK(*scaled == 5.0);
// optional
CHECK(first_even({1, 3, 5, 8}) == 8);
CHECK(first_even({1, 3, 5}).has_value() == false);
// 15.4 noexcept 保证的移动(编译期验证)
static_assert(std::is_nothrow_move_constructible_v<Movable>);
Movable m1;
m1.data = std::string(100, 'x');
Movable m2 = std::move(m1);
CHECK(m2.data.size() == 100);
// 15.8 防御性编程:断言与输入验证
int n = -5;
if (n < 0) {
// 提前返回/处理失败分支
CHECK(n < 0);
} else {
CHECK(false);
}
if (failures == 0) std::println("全部通过");
return failures;
}