测试_第15章_错误处理.cpp

← 测试总览 · 目录

编译运行: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;
}